​该场链接​

A. Polycarp and Coins

Codeforces Round #734 (Div. 3)A - C_字符串

题意:

用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

Codeforces Round #734 (Div. 3)A - C_i++_02

题意:

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

思路:

首先找到重复次数大于等于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

Codeforces Round #734 (Div. 3)A - C_i++_03

题意:

对一个字符串中的字母染成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

Codeforces Round #734 (Div. 3)A - C_i++_04

题意:

给你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;
}
}