cf1209 A~D

传送门

A Paint the Numbers

思路:

排序后从小到大枚举,每次都将当前数的倍数并且未染色的数跟该数染同一种颜色。

代码:

int n,a[maxn],res;
int vis[maxn];
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	sort(a+1,a+1+n);
	for(int i=1;i<=n;i++){
		if(vis[i]) continue;
		res++;vis[i]=res;
		for(int j=i+1;j<=n;j++){
			if(!vis[j]&&a[j]%a[i]==0){
				vis[j]=res;
			}
		}
	}
	cout<<res<<endl;
	return 0;
} 

B Koala and Lights

思路:

暴力跑1e5个时刻,检测当前的灯的状态,取\(max\)

代码:

int n;
int a[110];
PII p[110];
int res=0;

int main(){
	cin>>n;
	for(int i=1;i<=n;i++) scanf("%1d",&a[i]);
	for(int i=1;i<=n;i++){
		cin>>p[i].first>>p[i].second;
	}
	for(int i=1;i<=n;i++){
		if(a[i]) res++;
	}
	for(int k=0;k<=100000;k++){
		int tmp=0;
		for(int i=1;i<=n;i++){
			if(k>=p[i].second&&(k-p[i].second)%p[i].first==0) a[i]^=1;
			if(a[i]) tmp++;
		}
		res=max(res,tmp);
	}
	cout<<res<<endl;
	return 0;
} 

C Paint the Digits

思路:

考虑每个位置的数字只有\(0~9\)一共\(10\)种可能,枚举这\(10\)个数字。
每次:
对于小于该数字的数,放到第一个子序列;
对于大于该数字的数,放到第二个子序列;
如果等于的话:维护一下第二个子序列的最大值,如果该数小于最大值的话,放到第一个子序列,反之放到第二个子序列。
check的时候,先检查第一个子序列再检查第二个子序列。
维护一个最大值,如果不是单调递增的话就不可行。

代码:

const int maxn=200000+10;
int a[maxn],b[maxn],n;
bool check(int x){
	memset(b,0,sizeof b);
	int las1=0,las2=0;
	for(int i=1;i<=n;i++){
		if(a[i]<x){
			b[i]=1;las1=max(las1,a[i]);
		}
		else if(a[i]>x){
			b[i]=2;las2=max(las2,a[i]);
		}
		else{
			if(a[i]>=las2) b[i]=2;
			else b[i]=1;
		}
	}
	int maxx=0;
	for(int i=1;i<=n;i++)
		if(b[i]==1){
			if(maxx<=a[i]) maxx=a[i];
			else return 0;
		}
	for(int i=1;i<=n;i++)
		if(b[i]==2){
			if(maxx<=a[i]) maxx=a[i];
			else return 0;
		}
	return 1;
}
int main(){
	int _=read;
	while(_--){
		n=read;
		for(int i=1;i<=n;i++) scanf("%1d",&a[i]);
		int flag=0;
		for(int i=0;i<=9;i++){
			if(check(i)){
				flag=1;break;
			}
		}
		if(flag){
			for(int i=1;i<=n;i++)
				printf("%d",b[i]);
			puts("");
		} 
		else printf("-\n");
	}
	return 0;
} 


D Cow and Snacks

思路:

思维建图+并查集。
考虑每次将一个人喜欢的花合并,这样对于一个大小为\(x\)的连通块来说,最多能够满足\(x-1\)个人的需求。

代码:

int root[maxn];
int Find(int x){
   if(x!=root[x]) root[x]=Find(root[x]);
   return root[x];
}
int main(){
   int n=read,k=read;
   int res=0;
   for(int i=1;i<=n;i++) root[i]=i;
   for(int i=1;i<=k;i++){
   	int u=read,v=read;
   	int fu=Find(u),fv=Find(v);
   	if(fu!=fv) root[fu]=fv;
   }
   for(int i=1;i<=n;i++)
   	if(i==Find(i)) res++;
   cout<<k-(n-res)<<endl;	
   return 0;
} 

posted @ 2021-05-11 14:10  OvO1  阅读(79)  评论(0编辑  收藏  举报