Problem - A - Codeforces

题意:给定 0≤a,b,c≤20,判定其中是否有一个数等于另两数之和,若是输出 YES,否则输出 NO

思路:模拟

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int a , b , c;
		cin >> a >> b >> c;
		if((a == b + c) ||(b == a + c) ||(c == a + b))cout <<"Yes\n";
		else cout <<"No\n";
	}

Problem - B - Codeforces

题意:给定一个长为 n 的序列 a,判断你是否能通过重排的方式使序列严格递增。

严格递增:形式上的,有 a1​<a2​<⋯<an​。

思路:严格单增的条件是没有重复的,模拟即可

// Code Start Here	
	int t;
	cin >>t;
	while(t--){
		int n;
		cin >> n;
		vector<int> a(n);
		for(int i = 0;i<n;i++)cin >>a[i];
		map<int,int>mp;
		for(int i = 0;i<n;i++)mp[a[i]]++;
		bool f = true;
		for(auto [k,v] : mp){
			if(v > 1)f = false;
		}
		if(f)cout <<"Yes\n";
		else cout <<"No\n";
	}

Problem - C - Codeforces

题意:8×8 的染色地图,初始是白色,给你染完色的地图,. 代表白色,R 代表红色,B 代表蓝色。

其中染红色的策略必定是涂一行,染蓝色的策略必定是涂一列。颜色会覆盖。

求最后涂的颜色是什么,R代表红,B 代表蓝。

思路:非红即蓝,只要行全红一定是红  否则是蓝

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		vector<string> v(8);
		for(int i = 0;i<8;i++)cin >> v[i];
		bool f = false;
		for(string s : v){
			if (s == "RRRRRRRR") f = true;
		}
		if(f)cout <<'R' << endl;
		else cout <<'B' << endl;
	}

Problem - D - Codeforces

题意:给定一个长为 n (2≤n≤2×105) 的序列 a (1≤ai​≤1000),求 gcd(ai​,aj​)=1max​{i+j}。换句话说,求 i+j 的最大值,其中 i,j 满足 ai​ 和 aj​ 互质。

思路:观察到序列长度为1e5但是数据范围很小,想到可以离散化,由于题目要求求最大max(ai,aj),若对于同一个ai,aj出现多次,显然选择最后出现的位置最优。离散化之后模拟即可,数据范围1010 ^ 2可以接受

// Code Start Here
	int t;
	cin >> t;
	while(t--){
		int n;
		cin >> n;
		vector<int> a(N);
		for(int i = 1;i<=n;i++)cin >>a[i] ;
		vector<int> vis(M,-1);
		for(int i = 1;i<=n;i++)vis[a[i]] = max(vis[a[i]],i);
		vector<int> v;
		for(int i = 1;i<M;i++)if(vis[i]!=-1)v.push_back(vis[i]);
		int ans = -1;
		for(int i = 0;i<int(v.size());i++){
			for(int j = i;j<int(v.size());j++){
				if(gcd(a[v[i]],a[v[j]]) == 1){
					ans = max(ans,v[i] + v[j]);
				}
			}
		}
		cout << ans <<endl;
	}

Problem - E - Codeforces

题意:

有 n 阶楼梯,当前楼梯与上一阶楼梯的高度差为 ai​(a1​ 就是第一节阶梯的高度)。

q 次询问,对于每一个 ki​ (1≤i≤q),若 Timur 一步能提高 ki​ 的高度,求出他能到达的最高高度。

思路:

观察到楼梯的位置高度单调递增,显然可以用前缀和记录。其次思考到如果遇到一个跨不上去的,那么这个后面的也跨不上去,要跨上楼梯所需要的步长在优化后也具有单增的性质,前缀和+二分即可

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		memset(s , 0 , sizeof s);
		int n , q;
		cin >> n >>  q;
		for(int i = 1;i<=n;i++){
			cin >> a[i];
			s[i] = s[i-1] + a[i];
			a[i] = max(a[i-1] ,a[i]);
		}
		while(q--){
			int x;
			cin >> x;
			cout << s[(upper_bound(a+1,a+1+n,x)-a-1)] << " ";
		}
		cout << endl;
	}
	return 0;	

Problem - F - Codeforces

题意:你有两个字符串 s 和 t,它们初始都为 a,你会对字符串进行 q 次操作两种类型的操作:
1kx ,在 s 末尾添加字符串 k 恰好 x 次
2kx ,在 t 末尾添加字符串 k 恰好 x 次
求每次操作之后,是否可以重新排列 s 和 t 的字符,使 s 字典序比 t 小,如果可以,则输出“YES”,否则输出“NO”。

思路:如果 t 中有一个字符不是 a,那么只要把那个字符移到第一位,就可以满足 s 的字典序小于 t,而如果两个字符串中都只有 a就比较两个s的大小即可

// Code Start Here	
	int t;
	cin >> t;
	while(t--){
		int val_a=0,val_b=0,flag1=0,flag2=0;
		int q;
		cin >> q;
		while(q--){
			int op , x;
			string a;
			cin >> op >> x >> a;
			if(op==1){
				for(int i=0;i<int(a.size());i++) if(a[i]!='a') flag2=1;
				val_a+=x*int(a.size());
			}
			else{
				for(int i=0;i<int(a.size());i++) if(a[i]!='a') flag1=1;
				val_b+=x*int(a.size());
			}
			if(!flag1&&flag2) cout<<"No"<<endl;
			else if(flag1) cout<<"Yes"<<endl;
			else if(val_a<val_b) cout<<"Yes"<<endl;
			else cout<<"No"<<endl;
		}
	}
	return 0;	

Problem - G - Codeforces

题意:我们定义前缀或的意思是 ori​=ori−1​orai​。重排数组 a,使得它的前缀或数组的字典序最大。

思路:为了保证字典序最大,b1​ 一定是 a 中最大的数,然后依次确定 b2​,b3​,…bn​。想要确定 bi​,只需要枚举还没有选择的 aj​,使得 bi​=bi−1​oraj​ 最大 即可。

// Code Start Here	
	int t;cin >> t;while(t--){
		const int N = 2e5+10;
		int n;
		cin >> n;
		vector<int> a(N);
		vector<bool> vis(N,false);
		for(int i = 1;i<=n;i++)cin >> a[i];
		int now = 0;
		for(int i = 1;i<=min(n,60LL);i++){
			int anow = -1;
			int temp;
			for(int j = 1;j<=n;j++){
				if(!vis[j] && anow <(now | a[j])){
					anow = (now | a[j]);
					temp = j;
				}
			}
			vis[temp] = true;
			now |= a[temp];
			cout << a[temp] <<" ";
		}
		for(int i = 1;i<=n;i++){
			if(!vis[i])cout << a[i] <<" ";
		}
		cout <<endl;		
	}

Logo

集算法之大成!助力oier实现梦想!

更多推荐