Codeforces Round #827 (Div. 4)——A-G

A:

题意:给定三个数字,问是否能够构成两个数之和等于另一个数。

方法:将三个数字排序,判断前两个数相加是否等于最后一个数 

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n;
int a[N];

int main(){
	cin>>t;
	while(t--){
		memset(a,0,sizeof(a));
		for(int i=1;i<=3;i++) cin>>a[i];
		sort(a+1,a+4);
		if(a[1]+a[2]==a[3]) cout<<"YES\n";
		else cout<<"NO\n";
	}
}

 B:

题意:给一个长度为N的数组,判断是否能构成严格单调递增的数组。

方法:如果数组中的每个数仅出现一次,那么一定可以构成,否则不能。 

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long ll;
int t,n,a[N];
set<int>e;//set容器自动消除重复的元素

int main(){
	cin>>t;
	while(t--){
		cin>>n;e.clear();
		for(int i=1;i<=n;i++){
			cin>>a[i];e.insert(a[i]);
		}
	    if(e.size()==n) cout<<"YES\n";//如果容器里面的大小等于数组大小,则说明数各不相等
	    else cout<<"NO\n";
	}
}

 C:

题意:给一个8x8的板子,经过别人涂色过后(只有两种颜色,R、B),(注意:每次图色,只能是涂一行或者涂一列相同的颜色),求最后一次涂的颜色是什么颜色?

方法:因为经过多次涂色过后,肯定会有颜色覆盖,那么我们从行的角度来考虑,如果某一行全是R(B),那么最终的颜色就是R(B)。

 代码:

#include <bits/stdc++.h> 
using namespace std;
string s;
void solve(){ 	
	bool ok = false;
	for(int i = 1; i <= 8; i++){ 
		cin >> s;
		if(s == "RRRRRRRR") ok = true;
	}
	if(ok) cout<<"R\n";
	else cout<<"B\n";
}

int main(){ 
	int T;cin >> T;
	while(T--) solve();
}

D: 

 

题意:给定一个长度为N且不可改动的数组,若能求出数组中两个数a[i]=A,a[j]=B,A与B互为质数且i+j是最大,输出max(i+j),否则输出-1。 

方法:因为N<=10000,所以可以用枚举。记录数组中每个数的下标,再依次枚举答案。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=1e4;
int idx[N];//idx数组用于记录下标

void solve(){
	int n;cin>>n;memset(idx,0,sizeof(idx));
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		idx[x]=i;
	}
	int ans=-1;
	for(int A=1;A<=10000;A++)
	for(int B=1;B<=10000;B++)
		if(idx[A]>0&&idx[B]>0&&__gcd(A,B)==1) //如果A和B对应的下标存在,且A和B互为质数
			ans=max(ans,idx[A]+idx[B]);
	cout<<ans<<"\n";
}

		

int main(){
	int T;cin>>T;
	while(T--){
		solve();
	}
}

E: 

 

题意:给了N阶楼梯,每一阶的高度为ai,进行Q次询问,每次询问给定一个高度H,如果H>ai,则可以爬上这阶楼梯,否则就不能爬上这阶楼梯。 求能爬多高?

前置知识:upper_bound(二分) 

链接:https://blog.csdn.net/qq_40160605/article/details/80150252

方法:因为upper_bound是从数组中最小的元素到最大的元素依次查找,所以我们需要用一个数组来维护阶梯的高度,再用sum数组维护前缀和,最后输出值。

代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=2e5+10;
int a[N],b[N],sum[N];

void solve(){
	int n,q;
	cin>>n>>q;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=max(b[i-1],a[i]);//用b数组维护前个最大值
		sum[i]=sum[i-1]+a[i];//sum数组维护前缀和
	}
	//cout<<"b[]:";
	//for(int i=1;i<=n;i++) cout<<b[i]<<" ";
	//cout<<"sum[]";
	//for(int i=1;i<=n;i++) cout<<sum[i]<<" ";
	while(q--){
		int x;cin>>x;
		int t=upper_bound(b+1,b+1+n,x)-b-1;//第一个大于x的位置:upper_bound(b+1,b+1+n,x)-b
		//cout<<"t:"<<t<<" ";
		//cout<<"ans="<<sum[t]<<" "<<endl;
		cout<<sum[t]<<" ";
	}
	puts("");
}

signed main(){
	int T;cin>>T;
	while(T--){
		solve();
	}
}

 F:

 题意:给两个字符串,并初始都是"a",进行选择操作,op=1是在第一个字符串后面加k个字符串,op=2是在第二个字符串后面加k个字符串。(拼接的字符串是可以改变字母位置的),问能否满足拼接后的字符串a<b,能则输出YES,否则初始NO。

方法:因为拼接字符串的过程中,字母位置可以改变,如果想使第一个字符串<第二个字符串的,那么就尽可能的将不是字母‘a’的字母放在前面,才能尽可能使第二个字符串>第一个字符串

这里举样例1:

 得出的贪心策略:如果在添加字符串时,出现了非'a'的字母,如果是op=1,则是NO,如果是op=2,则是YES。如果拼接后,两个字符串相等,则比较长度。

 代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=5e5+10;
char s[N];

int main(){
	int T;cin>>T;;
	while(T--){
		int n;cin>>n;
		ll c1=1,c2=1,p1=0,p2=0;
//c1、c2分别统计字符串1和2中字母‘a’的个数,p1表示字符串1中有非'a'字母,p2同理
		while(n--){
			int op,k;
			scanf("%d%d%s",&op,&k,s+1);
			if(op==1)
			for(int i=1;s[i];i++){
				if(s[i]=='a') c1+=k;
				else p1=1;
			}
			else
			for(int i=1;s[i];i++){
				if(s[i]=='a') c2+=k;
				else p2=1;
			}
//如果p2出现了非'a'字母,或者字符串相等,c1<c2
			if(p2||c1<c2&&p1==0) cout<<"YES\n";
			else cout<<"NO\n";
		}
	}
}

 G:

 题意:给定一个长度为N的数组a,输出一个同等长度的数组b。b数组满足

 方法:暴力枚举。

要使b数组的字典序最大,就是每个前缀或都是最大的,所以我们直接求前缀或每个部分的最大值即可。采用两次遍历,每次都求出对应的前缀或最大值。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
typedef long long ll;
int a[N];
inline void solve(){
	int n;cin>>n;int idx;
	for(int i=1;i<=n;i++) cin>>a[i];
	int cur=0;//上一个部分最大的前缀或
	for(int i=1;i<=n;i++){
		int mx=0;//记录最大前缀或
		for(int j=i;j<=n;j++){//从上一次前缀或的最后一个元素开始找最大前缀或
			if((a[j]|cur)>mx){
				mx=(a[j]|cur);
				idx=j;
			}
		}
		swap(a[i],a[idx]);//更换位置,使得前缀或最大
		if(cur!=mx) cur=mx;//如果上一部分的最大前缀或不是最大的,则更新最大的
		else break;
//如果上一次最大前缀或是等于下一次最大前缀或的,则说明后面的元素值已经没有贡献了
	}
	for(int i=1;i<=n;i++) cout<<a[i]<<" ";
	cout<<"\n";
}

int main(){
	int T;cin>>T;
	while(T--) solve();
}

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值