AtCoder Regular Contest 112 Summary

AtCoder Regular Contest 112 Summary

A - B = C:统计+数学

考虑固定 C C C,即 A = B + C A=B+C A=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 = L R − L R − i − L + 1 \sum_{i=L}^{R-L}{R-i-L+1} i=LRLRiL+1

化简一下:
∑ i = L R − L R − i − L + 1 = ( R − L + 1 ) ( R − 2 L + 1 ) − ∑ i = L R − L i = ( R − L + 1 ) ( R − 2 L + 1 ) − ( R − L + L ) ( R − 2 L + 1 ) 2 = ( R − L + 1 ) ( R − 2 L + 1 ) − R ( R − 2 L + 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 < L R-L<L RL<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:动态规划+树+贪心

f x f_x fx表示以 x x x为根的子树先手与后手的金币差, s z x sz_x szx表示子树大小。

我们可以递归解决问题。

y ∈ s o n x y\in son_x ysonx,分三种情况:

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

这样的话,我们每一次把这些 f f f存起来排序,就用 O ( n log ⁡ 2 n ) 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)走来时,可以知道 x x x行以及 y y y列都必须有一个停留点。

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

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

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值