Codeforces Round #734 (Div. 3)A - C

76 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

该场链接

A. Polycarp and Coins

题意:

用1和2凑出n来,并使得1和2的个数的差值最小;

思路:

先将n粗略地分为3份,其中2的贡献大约是1的两倍,即如果n是3的倍数,那么2的数量应该等同于1的数量,接下来再考虑n不是3的倍数的情况:

  • 如果n%3 == 1,即在满足2的数量等于1的数量时,多出一个1,此时1的数量+1;
  • 如果n%3 == 2,同理:2的数量多出一个。
#include<bits/stdc++.h>
using namespace std;
#define ll long long


int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		ll n;
		cin>>n;
		ll ans = n/3;
		if(n%3 == 0)
		{
			cout<<ans<<" "<<ans<<endl;
		}
		else if(n%3 == 1)
		{
			cout<<ans+1<<" "<<ans<<endl; 
		}
		else
		{
			cout<<ans<<" "<<ans+1<<endl;
		}
	}
}

B1. Wonderful Coloring - 1

题意:

用红绿两种颜色对一个字符串中的字母染色(可以不染),要求同一个字母颜色不同且红色和绿色字母个数相同,求染成红色的字母的最大个数

思路:

首先找到重复次数大于等于2的字母:该字母能被染成红色和绿色各一次 然后找到所有出现一次的字母:该类字母能被染成红色和绿色 最终结果就是第一种字母的数量加上(第二种字母数量/2)。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
char a[100];
map<char,int>vis;


int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		vis.clear();
		scanf("%s",a+1);
		int n = strlen(a+1);
		int ans = 0;
		int cnt = 0;
		for(int i = 1; i <= n; i++)
		{
			if(!vis[a[i]])
			{
				ans++;
				
			}
			vis[a[i]]++;
		}
		for(int i = 1; i <= n; i++)
		{
			if(vis[a[i]] == 1)
			{
				cnt++;
				ans--;
			}
		}
		cout<<ans + cnt/2<<endl;
	}
}

B2. Wonderful Coloring - 2

题意:

对一个字符串中的字母染成k种不同的颜色,且每种颜色的字母数相相同且不重复,使得最终被染色的字母总数最大,输出染色方案

思路:

和上一题类似 1,先找到出现次数大于等于k的字母:这些字母能被染成k种颜色,多余的染不了; 2,然后把剩下的小于等于k的字母染成不同的颜色 关于第二点,要注意应该把同样的字母排在一起依次染色,否则可能让相同的字母染上相同的颜色,在这题数据量达到2e5的情况下,我采用了类似于 邻接表(数组版)的方法去实现将同种颜色的字母挨个染色的目的。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int a[200010];
int vis[200010];
int ans[200010];
int col[200010];
int pos[200010];
struct node{
	int last;
	int pos;
}e[200010];
int d[200010];
int flag[200010];
int flag2[200010];

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(ans,0,sizeof(ans));
		memset(d,0,sizeof(d));
		memset(flag,0,sizeof(flag));
		memset(flag2,0,sizeof(flag2));
		memset(vis,0,sizeof(vis));
		memset(col,0,sizeof(col));
		int n,k;
		cin>>n>>k;
		for(int i = 1; i <= n; i++)
		{
			scanf("%d",&a[i]);
			vis[a[i]]++;
		}
		int cnt = 0,num = 0;
		int m = 0;
		for(int i = 1; i <= n; i++)
		{
			
			if(vis[a[i]] < k)
			{
				if(flag2[a[i]] == 0)
				flag2[a[i]] = 1;
				else if(flag2[a[i]] == 1)
				flag2[a[i]] = 2;
				e[++cnt].last = d[a[i]];
				e[cnt].pos = i;
				d[a[i]] = cnt;
			}
			if(flag2[a[i]] == 1)
			{
				pos[++m] = a[i];
			}
			
		}
		cnt = 0;
		
		for(int i = 1; i <= n; i++)
		{
			if(vis[a[i]] < k)
			{
				num += vis[a[i]];
				flag[i] = 1;
				vis[a[i]] = 0;
			}
		}
		num -= (num%k);
		int now = 0;
		for(int i = 1; i <= n; i++)
		{
			if(flag[i] == 0 && col[a[i]] < k)
			{
				ans[i] = ++col[a[i]];
			}
		}
		now = 0;
		for(int i = 1; i <= m; i++)
		{
			
			for(int j = d[pos[i]]; j; j = e[j].last)
			{
				if(num > 0)
				{
					ans[e[j].pos] = ++now;
					num--;
					if(now >= k)now = 0;
				}
			}
		}
		
		for(int i = 1; i <= n; i++)
		{
			printf("%d ",ans[i]);
		}
		cout<<endl;
	}
}

C. Interesting Story

题意:

给你n个只有'a','b','c','d','e'组成的字符串,让你选择最大的字符串数量,使得选择的这些字符串中某个字符的数量大于其它所有字符的数量

思路:

因为仅出现5种字母,因而我们可以考虑对5种字母进行枚举,考虑每一个字母在各自的串中的贡献,例如:串aaacee,在该串中,字母a的贡献为:3-3 = 0,c的贡献为1-5 = -4; 对这些贡献由大到小排序,再依次累加,当累加的贡献小于等于0时,就是该字母作为最大字符数时所能选择的最多的串; 然后取五次结果中的最大值即为答案。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
string a[200010];
struct node{
	int num;
	int a,b,c,d,e;
}vis[200010];
int num[1000];
bool cmpa(node a, node b)
{
	return a.a > b.a;
}
bool cmpb(node a, node b)
{
	return a.b > b.b;
}
bool cmpc(node a, node b)
{
	return a.c > b.c;
}
bool cmpd(node a, node b)
{
	return a.d > b.d;
}
bool cmpe(node a, node b)
{
	return a.e > b.e;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		memset(vis,0,sizeof(vis));
		memset(num,0,sizeof(num));
		int n,cnt = 0;
		cin>>n;
		for(int i = 1; i <= n; i++)
		{
			cin>>a[i];
			for(int j = 0; j < a[i].size(); j++)
			{
				num[a[i][j]]++;
			}
			vis[i].a = 2*num['a']-(a[i].size());
			vis[i].b = 2*num['b']-(a[i].size());
			vis[i].c = 2*num['c']-a[i].size();
			vis[i].d = 2*num['d']-a[i].size();
			vis[i].e = 2*num['e']-a[i].size();
			memset(num,0,sizeof(num));
		}
		sort(vis+1,vis+1+n,cmpa);
		int ans = 0,now = 0,maxx = 0;
		for(int i = 1; i <= n; i++)
		{
			maxx += vis[i].a;
			if(maxx > 0)ans++;
			else break;
		}
		sort(vis+1,vis+1+n,cmpb),maxx = 0,now = 0;
		for(int i = 1; i <= n; i++)
		{
			maxx += vis[i].b;
			if(maxx > 0)now++,ans = max(ans,now);
			else break;
		}
		sort(vis+1,vis+1+n,cmpc),now = 0,maxx = 0;
		for(int i = 1; i <= n; i++)
		{
			maxx += vis[i].c;
			if(maxx > 0)now++,ans = max(ans,now);
			else break;
		}
		sort(vis+1,vis+1+n,cmpd),now = 0,maxx = 0;
		for(int i = 1; i <= n; i++)
		{
			maxx += vis[i].d;
			if(maxx > 0)now++,ans = max(ans,now);
			else break;
		}
		sort(vis+1,vis+1+n,cmpe),now = 0,maxx = 0;
		for(int i = 1; i <= n; i++)
		{
			maxx += vis[i].e;
			if(maxx > 0)now++,ans = max(ans,now);
			else break;
		}
		cout<<ans<<endl;
	}
}