codeforces div2-- #659

A、C两道题题解

一.A题

A题题目链接

(1)题意:

t 组测试数据,每组数据有 n 个数 ai,代表着 si 行字符串与 s(i-1)行字符串有多少个 ai 相同前缀字符
每组测试数据输出 n + 1行字符串,第二行开始与前一行有 ai 个相同前缀字符

(2)题解:

  1. 第 i 行的字符串的长度应该是 max(ai,a(i+1))决定 ,利用一个str数组来存储字符的变化情况,初始化为全部相同字符
  2. 所以第一行先输出一个全部相同的字符串,并且长度为最长,例如:aaaaaaa 方便后面输出
  3. 从第二行开始,每一行先输出str数组中相同前缀,然后假如下一行的前缀数 a(i+1) > ai 还得把str数组中的字符 + 1输出 a(i+1) - ai次

(3)代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6 + 10;
int t,n,a[maxn];
char str[200];
int main()
{
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		fill(str,str+110,'a');
		memset(a,0,sizeof(a));
		for(int i = 1; i <= n; i++)
			scanf("%d",&a[i]);
		printf("%s\n",str);
		for(int i = 1; i <= n; i++)
		{
			for(int j = 1; j <= a[i]; j++)
				printf("%c",str[j]);
			for(int j = a[i] + 1; j <= a[i + 1] + 1; j++)
			{
				str[j] = (str[j] + 1) % 123;
				if(str[j] < 97)
					str[j] += 97;		//限定为小写英文字母的ascii值 
				printf("%c",str[j]);
			}
			printf("\n");
		}
	}
	return 0;
 } 

二.C题

C题题目链接

(1)题意:

给t组数据,长度为 n 的两个字符串 s1,s2 ,可以选择一个位置 k ,然后将s1[i] ~ s1[k]中等于s1[k]的字符都变成另外一个大于s1[k]的字符
例如 acbbdb 就可以把第三位、第四位、第六位的 b 都变成任何一个大于 b 的字符,例如变成 acccdc 或者 acdddd ……
当有s1[i] > s2[i]的字符存在时候,输出-1
问最少能用几次把s1串变成s2串

(2)题解:

贪心的想法 – 尽量一次能够变化多的字符可能会最省次数,字符变化成多少由最小的对应s2串的值决定
例如:s1 : aab s2 : bcc
就只能aa -> bb — bbb,然后在 bb -> cc — bcc

(3)代码:

#include <cstdio>
#include <cstring>
#include <vector> 
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn = 30;
int t,flag,n,ans;
int main()
{
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&n);
		string s1,s2;
		cin>>s1>>s2;
		
		flag = 0;
		ans = 0;
		vector <int> v[maxn];
		
		for(int i = 0; i < n; i++)
		{
			if(s1[i] > s2[i])
				flag = 1;
			else if(s1[i] < s2[i])
				v[s1[i] - 'a'].push_back(i);
				//根据s1[i]的字符大小,把 i 分成不同类 
		}
		if(flag == 1)
		{
			printf("-1\n");
			continue;
		}
		
		for(int i = 0; i < 20; i++)
		{	//从小到大开始遍历 'a' -> 't' 
			char minn = 'z';	//把minn初始化设置为一个不会影响结果的值 
			
			int num = v[i].size(); 
			if(num > 0)
				ans++;
				// num中有值,说明需要一次修改
				 
			for(int j = 0; j < num; j++)
				minn = min(minn,s2[v[i][j]]);
				//把相同s1串的值改为最小的那个s2串对应位置的值 
			for(int j = 0; j < num; j++)
				if(s2[v[i][j]] > minn)
					v[minn - 'a'].push_back(v[i][j]);
					//修改之后,这些相同的s1串的值就变成了 minn
					//然后再把剩下的这些加入到对应的 v[minn - 'a'] 位置去
		}
		printf("%d\n",ans);
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值