(Training 8)Codeforces Round #692

和arc差不多一样 签到题很友好

A - In-game Chat

就是判断右边开始连续括号的数量


#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
char str[N];
int main(){
    
    
	int T;
	cin>>T;
	while(T--){
    
    
		int n;
		cin>>n;
		cin>>str+1;
		int len=0;
		for(int i=n;i>=1;i--){
    
    
			if(str[i]==')')len++;
			else break;
		}
		if(len>n-len)puts("Yes");
		else puts("No");
	}
	return 0;
}

B Fair Numbers

原本一看以为很难 突然发现 18位暴力即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
bool st[10];
bool check(LL x){
    
    
	memset(st,0,sizeof st);
	LL temp=x;
	while(temp){
    
    
		st[temp%10]=1;
		temp/=10;
	}
	for(int i=1;i<=9;i++){
    
    
		if(st[i]){
    
    
			if(x%i)return 0;
		} 
	}
	return 1;
}
int main(){
    
    
	int T;
	cin>>T;
	while(T--){
    
    
		LL n;
		cin>>n;
		for(LL i=n;;i++){
    
    
			if(check(i)){
    
    
				printf("%lld\n",i);
				break;
			}
		}
	}
	return 0;
}

C. Peaceful Rooks

题意:把所有点移动到对角线上 棋子不能互相伤害 每个棋子会攻击同行同列
问最少移动的操作数
思路:移动时要使得操作数最少那么肯定是只移动一步即行数的对角线上或者列数的对角线上 那么这时候就有个问题移动的位置是否会被攻击如果2个位置只被占领一个 那么可以往其中一个走
但是碰到了2个都被占领的情况 就有问题了 模拟一下 如果是在行列分别为x y(x!=y)的棋子要移动
如果x列或者y行都被占领 那么占领x列或者占领y行的棋子要先移动 一直这样模拟下去到最后(去移动占领x列的棋子 和占领y行的棋子) 如果行成了环状 那么有一个点必然被牺牲 他要多移动一步 如果没有形成环状 那么答案就是点数 所以我们可以把它当作一个强联通分量 我们要求的就是强连通分量的数量
但是我们只需要判断首尾相接的联通块的数量和不在对角线上点的数量 那么我们只需要用并查集来维护即可
即如果一点不在对角线上 让x和y连接起来 ans++ 如果x和y已经连接在一起了 那么形成了一个强联通分量 ans++
最后输出即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int p[N];
int find(int x){
    
    
	if(p[x]!=x)p[x]=find(p[x]);
	return p[x];
}
void init(){
    
    
	for(int i=1;i<N;i++)
	p[i]=i;
}
int main(){
    
    
	int T;
	cin>>T;
	while(T--){
    
    
		init();
		int n,m;
		scanf("%d%d",&n,&m);
		int ans=0,flag=0;
		for(int i=1;i<=m;i++){
    
    
			int x,y;
			scanf("%d%d",&x,&y);
			if(x==y)continue;
			ans++;
			x=find(x),y=find(y);
			if(x==y){
    
    
				flag++;
			}
			p[x]=y;
		}
		cout<<ans+flag<<endl;
	}
	return 0;
}

D. Grime Zoo

题意:给定字符串只包含’0’和’1’和’?’
和01串的价值x 和10串的价值y
'?‘可以变换为0或者1 求出最小价值
思路:如果10串价值大 我们应该让10串尽量少 所以把0放在前面
如果01串价值大 那么我们直接反转字符串 和交换x和y的值
所以我们首先从前往后把所有的’?‘都当作’0’然后计算出总价值 再从后面往前推一次 依次把’?'换成’1’每次求出总价值 与答案去最小值 这时候最终结果就是最小值 从后往前依然为贪心过程 我们把后面的0串改为1那么后面的0减少那么形成的10又会减少那么总价值会降低

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int l[5],r[5];
int main(){
    
    
	string str;
	cin>>str;
	int x,y,n=str.length();
	cin>>x>>y;
	if(x>y){
    
    
		swap(x,y);
		reverse(str.begin(),str.end());
	}
	LL sum=0;
	for(int i=0;i<n;i++){
    
    
		if(str[i]=='1')l[1]++,sum+=1ll*x*l[0];
		else {
    
    
			l[0]++;sum+=1ll*y*l[1];
		}
	}
	LL ans=sum;
	for(int i=n-1;i>=0;i--){
    
    
		if(str[i]=='1')r[1]++,l[1]--;
		if(str[i]=='0')r[0]++,l[0]--;
		if(str[i]=='?'){
    
    
			l[0]--;
			sum-=1ll*l[1]*y+1ll*r[1]*x;
			sum+=1ll*l[0]*x+1ll*r[0]*y;
			r[1]++;
		}
		ans=min(ans,sum);
	}
	cout<<ans;
}

猜你喜欢

转载自blog.csdn.net/weixin_45663216/article/details/112753294