AtCoder Regular Contest 112 Summary

本文解析了AtCoder Regular Contest 112中涉及的三个题目,分别是统计与数学问题(A-B=C),分类讨论的B-–-B问题,以及动态规划与树的C-DFSGame。通过实例展示了如何运用数学技巧和编程策略解决这些挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AtCoder Regular Contest 112 Summary

A - B = C:统计+数学

考虑固定CCC,即A=B+CA=B+CA=B+C
∵A=B+C≤R,∴L≤B≤R−C.∴L≤C≤R−L. \because A=B+C\leq R,\\ \therefore L\leq B\leq R-C.\\ \therefore L\leq C\leq R-L.\\ A=B+CR,LBRC.LCRL.
答案就为∑i=LR−LR−i−L+1\sum_{i=L}^{R-L}{R-i-L+1}i=LRLRiL+1

化简一下:
∑i=LR−LR−i−L+1=(R−L+1)(R−2L+1)−∑i=LR−Li=(R−L+1)(R−2L+1)−(R−L+L)(R−2L+1)2=(R−L+1)(R−2L+1)−R(R−2L+1)2 \sum_{i=L}^{R-L}{R-i-L+1}\\ =(R-L+1)(R-2L+1)-\sum_{i=L}^{R-L}{i}\\ =(R-L+1)(R-2L+1)-\frac{(R-L+L)(R-2L+1)}{2}\\ =(R-L+1)(R-2L+1)-\frac{R(R-2L+1)}{2}\\ i=LRLRiL+1=(RL+1)(R2L+1)i=LRLi=(RL+1)(R2L+1)2(RL+L)(R2L+1)=(RL+1)(R2L+1)2R(R2L+1)

直接算即可,注意R−L<LR-L<LRL<L的情况。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll T,l,r;
int main(){
	cin>>T;
	for (;T;T--){
		cin>>l>>r;
		if (r-l<l){
			printf("0\n");
			continue;
		}
		ll sum=r*(r-l-l+1)/2;
		printf("%lld\n",(r-l+1)*(r-l-l+1)-sum);
	}
	return 0;
}

B - – - B:分类+数学

分类讨论。

我是在数轴上考虑的。

仔细讨论即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll b,c;
int main(){
	scanf("%lld%lld",&b,&c);
	if (b<0){
		if (abs(b)<c){
			if (c<=abs(b)*2) printf ("%lld",c*2-1);
			else printf ("%lld",c+2*abs(b));
		}
		else if (abs(b)==c){
			if (c>1) printf ("%lld",c*2-1);
			else printf ("%lld",2);
		}
		else{
			printf ("%lld",c*2-1);
		}
	}
	else if (b==0){
		printf ("%lld",c);
	}
	else{
		if (b<c){
			if (c<=b*2-1) printf("%lld",c*2-1);
			else printf ("%lld",abs(-b-c/2)*2-(!(c&1)));
		}
		else{
			if(c==1) printf("2");
			else printf ("%lld",c*2-1);
		}
	}
	return 0;
}

C - DFS Game:动态规划+树+贪心

fxf_xfx表示以xxx为根的子树先手与后手的金币差,szxsz_xszx表示子树大小。

我们可以递归解决问题。

y∈sonxy\in son_xysonx,分三种情况:

  1. fy<0,szy≡0(mod  2)f_y<0,sz_y\equiv0(\mod 2)fy<0,szy0(mod2),这样后手会将所有这样的结点都选一遍。
  2. fy≥0,szy≡0(mod  2)f_y\ge 0,sz_y\equiv0(\mod2)fy0,szy0(mod2),这样后手要避免选择yyy
  3. szy≡1(mod  2)sz_y\equiv1(\mod 2)szy1(mod2),这样的话后手每次都要选择较小的fyf_yfy

这样的话,我们每一次把这些fff存起来排序,就用O(nlog⁡2n)O(n\log_2^n)O(nlog2n)的时间复杂度算出来了。

#include<bits/stdc++.h>
#define N 100005
using namespace std;
int n,sz[N],f[N],la[N],to[N],ne[N],cnt=0,b[N];
void add(int x,int y){
	to[++cnt]=y;
	ne[cnt]=la[x];
	la[x]=cnt;
}
void dfs(int x){
	sz[x]=1;
	f[x]=1;
	for (int i=la[x];i;i=ne[i]){
		int y=to[i];
		dfs(y);
	}
	int len=0,sum=0;
	for (int i=la[x];i;i=ne[i]){
		int y=to[i];
		sz[x]+=sz[y];
		if (sz[y]&1){
			++len;
			b[len]=f[y];
		}
		else{
			if (f[y]<0) f[x]+=f[y];
			else sum+=f[y];
		}
	}
	if (len)sort(b+1,b+len+1);
	b[++len]=sum;
	for (int i=1;i<=len;i++)
		if (i&1) f[x]+=b[i];
		else f[x]-=b[i];
}
int main(){
	scanf("%d",&n);
	for (int i=2;i<=n;i++){
		int x;
		scanf("%d",&x);
		add(x,i);
	}
	dfs(1);
	cout<<((n+f[1])>>1);
	return 0;
}

D - Skate:并查集+图论

(x,y)(x,y)(x,y)这个点可以从(1,1)(1,1)(1,1)走来时,可以知道xxx行以及yyy列都必须有一个停留点。

(x,y)(x,y)(x,y)是一个平面时,那么我们将x,yx,yx,y合并。

因为有墙,所以将1,11,11,11,m1,m1,mn,1n,1n,1n,mn,mn,m合并,可以想到,最后答案就是集合数量减111,因为有列有行,我们取最小值。

#include<bits/stdc++.h>
using namespace std;
int n,m,fa[2005],t1[2005],t2[2005],s1,s2;
char a[1005][1005];
int find(int x){
	if (x==fa[x]) return x;
	else return fa[x]=find(fa[x]);
}
void Union(int x,int y){
	fa[find(x)]=find(y);
}
int main(){
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n+m;i++) fa[i]=i;
	for (int i=1;i<=n;i++){
		for (int j=1;j<=m;j++){
			a[i][j]=getchar();
			while (a[i][j]!='#'&&a[i][j]!='.') a[i][j]=getchar();
			if (a[i][j]=='#') Union(i,j+n);
		}
	}
	Union(1,n+1);
	Union(1,n+m);
	Union(n,n+1);
	Union(n,n+m);
	for (int i=1;i<=n;i++) t1[find(i)]=1;
	for (int i=n+1;i<=n+m;i++) t2[find(i)]=1;
	for (int i=1;i<=n+m;i++) s1+=t1[i];
	for (int i=1;i<=n+m;i++) s2+=t2[i];
	cout<<min(s1,s2)-1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值