Codeforces Round #828 (Div. 3)——A、B、C、D

A:

 题意:给定一个长度为N的整数数组,在数组选择一个数,将这个数转变为一个字母,再给定一个字符串,问这个数组能否转化为这个字符串。

方法:因为每次会将数组中相同的数转化为同一个字母,那么用map记录一下每个数字对应字母,最后再判断对应的位置,字母是否相同,相同则为YES,否则为NO。

 代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
map<int,int>mp;
int a[N];

inline void solve(){
	int n;cin>>n;mp.clear();
	for(int i=1;i<=n;i++) cin>>a[i];
	
	char s[N];cin>>s+1;
	
	for(int i=1;i<=n;i++)//记录
		if(!mp[a[i]]) mp[a[i]]=s[i];
	
	for(int i=1;i<=n;i++)//对比
		if(mp[a[i]]!=s[i]){
			cout<<"NO\n";return;
		}
	
	cout<<"YES\n";
}

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

 B:

 题意:给定一个长度为N的数组,输入op跟x,有两种操作,如果op=0,则是数组中的每个偶数都会加上x,如果op=1,则是数组中的每个奇数都会加上x。问,每次操作后,输出这个数组的sum

方法:这里如果我们遍历数组再更改数组,再用最后更改的数组求值,那么一定会TLE。所以,这里我们考虑记录原始数组中偶数和奇数的个数,因为每次操作,只会在偶数或者奇数上操作且加的x值都是一样的。(注意:这里加完过后,需要考虑奇偶个数的变化,以进行下一次的操作)

 代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;
map<int,int>mp;
int a[N];

inline void solve(){
	ll n,q;cin>>n>>q;
	ll sum=0,even=0,odd=0;
	for(int i=1;i<=n;i++) {
		cin>>a[i];sum+=a[i];
		if(a[i]%2==0) even++;//偶数个数
		else odd++;//奇数个数
	}
	while(q--){
		int op,y;
		cin>>op>>y;
		if(op==0){
			sum+=even*y;//求更改后的sum
			if(y%2==1) odd+=even,even=0;//判断奇数偶数个数的变化
		}
		else{//同上
			sum+=odd*y;
			if(y%2==1) even+=odd,odd=0;
		}
		cout<<sum<<"\n";
	}
}

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

 C:

题意:给定红绿灯的循环节,以及你初始看到的灯,求下一个绿灯等待的最长时间

方法:因为是循环节,所以将字符串的再复制一遍使其长度变为2n,再依次找最长时间。

(这题其实我也不明白为什么要找g跟r相差的最大值。)也许是这一句话吧?

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;


inline void solve(){
	int n;char c;string s;
    cin >> n >> c;
    cin >> s;
    s = "#" + s + s;
    int ans = 0, last = 0;
    for(int i = 2 * n; i >= 1 ; i -- ) {
        if(s[i] == 'g') last = i;
        if(s[i] == c) ans = max(ans, last - i);
    }
    cout << ans << endl;
}

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

D: 

 题意:给定一个数组,要求进行若干次操作,使得a[i]乘i上的数,每个数都能最多被乘一次,求最少的操作次数使得数组的乘积能够被2^n整除。

方法:补因子2

代码: 

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+10;
const int INF=0x3f3f3f3f;

inline void solve(){
	int n,cnt=0;
	cin>>n;
	vector<int>e;
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		while(x%2==0) x/=2,cnt++;//记录数组中因子2的个数
		int dx=0,idx=i;
		while(idx%2==0) idx/=2,dx++;//记录下标因子2的个数
		if(dx) e.push_back(dx);//将每个下标能分解因子2的个数存入vector
	}
	if(cnt>=n){//如果数组本身含有的因子2的个数大于等于N,则不用操作
		cout<<"0\n";return;
	}
	int res=n-cnt;//所需要补因子2的个数
	sort(e.begin(),e.end(),greater<int>());//降序排列
	int pos=0,ans=0;
	while(res>0 and pos<e.size()){//进行补因子2
		res-=e[pos++];ans++;
	}
	if(res>0) cout<<"-1\n";//补不完
	else cout<<ans<<"\n";//补完
}

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值