Codeforces Round #787 (Div.3) E、A-C

Codeforces Round #787 (Div. 3)

E. Replace With the Previous, Minimize

题意:

给定一个字符串s,你可以进行一下操作k次:

将s中所有字符变成前一个字符,例如可以所有c变成b、将所有a变成z

求:

k次操作后所得到的的字符串按字典序最小

题目要求按字典序最小,那我们就尽可能的把前面的字符变到最小:

情况1:

如果k>=25则所有字母都可以变成字符a(k的数据1e9就是唬人的)

情况2:

如果k次操作全部放在第一个字符,且操作完后第一个字符还不能是a

则将s中所有小于等于s[0]且大于s[0]-k的字符变成s[0]-k,否则原样输出。(此处用的是ascll

情况3:

如果k次操作内,第一个字符已经变成a,则去从前往后找到第一个k次操作不能变成a的字符t,然后记录字符taascll值,由于字符t前面已经操作了n次(n为这个字符t前所有可以变成a字符的操作数的最大值),那么这个字符最终只能变成char(t+(k-n))

例如样例中

4 19
ekyv

第三个字符y不能变成a,但是前面将ek变成a后,已经用了max('e','k')-'a'=10次,所以y只能变成y-(19-10)=p

故答案为:

aapp

完整代码:

#include<bits/stdc++.h>

using namespace std;

int a[200007];

void solve(){
	int n,k;
	cin >>n>>k;
	char s[n];
	getchar();
	for(int i=0;i<n;i++){
		scanf("%1c",&s[i]);
	}
	int num_c=0;
	
	if(k>=25){
		for(int i=1;i<=n;i++){
			cout <<'a';
		}printf("\n");
		return;
	}
	
	if(s[0]-'a'>k){
		cout <<char(s[0]-k);
		for(int i=1;i<n;i++){
			if(s[i]<=s[0]&&s[i]>s[0]-k){
				cout <<char(s[0]-k);
			}else{
				cout <<char(s[i]);
			}
		}
		printf("\n");
		return;
	}
	
	for(int i=0;i<n;i++){
		a[i+1]=s[i]-'a';
	}
	int num_p=0;
	char c;
	for(int i=1;i<=n;i++){
		if(a[i]<=k){
			num_c=max(a[i],num_c);
		}else{
			num_p=a[i];
			c = 'a'+a[i]-(k-num_c);
			break;
		}
	}
	
	for(int i=1;i<=n;i++){
		if(a[i]<=num_c){
			printf("a");
		}else{
			if(a[i]<=num_p&&a[i]>=num_p-(k-num_c)){
				printf("%c",c);
			}else{
				printf("%c",s[i-1]);
			}
		}
	}
	printf("\n");
}

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

A. Food for Animals

题意:

输入五个整数a b c d e

a代表现有狗粮的数量

b代表现有猫粮的数量

c代表现有通用粮的数量

d代表狗的数量

e代表猫的数量

求:

是否能满足每只猫、狗都分到一包粮。

签到题,数据在int范围。

核心代码:

    int a, b, c, x, y;
    std::cin >> a >> b >> c >> x >> y;
    if (a + c >= x && b + c >= y && a + b + c >= x + y) {
        cout << "YES\n";
    } else {
        cout << "NO\n";
    }

B. Make It Increasing

题意:

n个整数构成一个整数序列,你可以进行一下操作若干次:

将一个数除以2(向下舍入)

求:

是否若干次操作后得到一个严格升序的序列,若可以则输出操作的次数,若不能则输出-1

题意很简单,整数个数不超过2e5。

我们直接从整数序列末尾向前进行操作

完整代码:

#include<bits/stdc++.h>

using namespace std;

int a[200007];

void solve(){
	int n;
	cin >>n;
    
    //读入n个整数
	for(int i=1;i<=n;i++){
		cin >>a[i];
	}
    
	long long ans = 0;
	for(int i=n-1;i>=1;i--){
		while(a[i+1]<=a[i])//找到满足条件的a[i]
        {
            
			if(a[i]==0)//不满足严格升序
            {
				cout <<-1<<endl;
				return;
			}
            
			a[i]/=2;
			ans++;
		}
	}
	cout <<ans<<endl;
}

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

C. Detective Task

题意:

n个人依次参观一幅画,参观完后发现画丢了。小偷在这群人之中。询问这些人进入房间时画是否还在,他们会回答:

  • 0(画没了)
  • 1(画还在)
  • ?(俺也不知道)

小偷可以回答任意答案(牛马一个,盗窃犯法,切勿模仿)其他人只会回答真话,或者不知道(起码不是表面朋友)。

求:

可以盗窃这幅画的人数

我们由样例简单分析一下

当人数为时,肯定就是他是小偷(无论他说了什么)!

ans=1;


1234567(这是下标)

1110000(这是样例)

  • 此时小偷可能是第3个人是小偷(说了谎),第4个人说真话。

  • 或者第3个人说真话,第4个人是小偷(也说了真话,牛蛙)。

ans=2;


?????

  • 此时个人都可能偷画。

ans=5;


12345678(这是下标)

1?1??0?0(这是样例)

  • 假设第7个人是小偷,则说明第6个人说了真话,说明画已经丢了,则假设不成立。
  • 假设第2个人或第一个人是小偷,第3个人参观时画还在,相悖,假设不成立。

则第3 4 5 6个人可能是偷画的人

ans=4;


0?0???

  • 第一个人肯定是小偷,否则画一定在(朋友说真话)
  • ans=1

??11

  • 如果第三个人是小偷,则第四个人说的是0

则一定是第4个人

ans=1;


??0??

  • 若第三个人不是小偷,前两个之一必定是小偷
  • 若第三个人是小偷,则后两个肯定是朋友

ans=3;


由上述分析不难看出来

  1. 遇到0时,小偷一定在这个人之前或者是就是这个人
  2. 遇到?时,小偷可能会是他(如果前面没有0)
  3. 遇到1时,则这个人之前的?全部不是小偷,且这个人可能是小偷(说谎)

完整代码:

#include<bits/stdc++.h>

using namespace std;

void solve(){
	string s;
	cin >>s;
	bool p = false;
	int ans = 0;
	
	if(s.length()==1){//如果只有一个人,那么小偷必定是他
		cout <<1<<endl;
		return;
	}
	
	int ans_w=0,ans_1=0;//问号的数量和1的数量
	
	for(int i=0;i<s.length();i++){
		if(s[i]=='0'){
			if(s[i-1]=='1'||s[i-1]=='?'||i==0){
				cout <<1+ans_w+ans_1<<endl;
				return;
			}
		}else if(s[i]=='?'){
			ans_w++; 
		}else if(s[i]=='1'){
			ans_w=0;
			if(s[i-1]!='1') ans_1=1;
		}
		
		if(i==s.length()-1){
			cout <<ans_w+ans_1<<endl;
		}
		
	}
	
}

int main(){
	
	int T;
	cin >>T;
	while(T--){
		solve();
	}
	
	return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值