Codeforces Round #550 (Div. 3) A,B,C,D,E,F,G
前言
div3一时爽,一直div3一直爽。ak一时爽,一直ak一直爽。
这大概是打的最爽的一把cf了,虽然沾了div3和题目难度的光,但是offical rank 41 大概也是我能达到的巅峰了orz,场上6题,赛后补了G,1596->1740
.
但是这场比赛还是存在的一些问题的,其中最主要的就是A题的题意没有读懂的,导致队友过B了我还没有出A,后来完全推倒重来才在 14min
的时候勉强过A,中期表现其实还可以,后期也还算稳得住了吧,但是和真的大佬还是有差距orz,21min
过B,27min
过C,43min
1WA 过D,69min
1WA过E,86min
过F。
A. Diverse Strings
题意
给定一个字符串,判断其是否连续且不重
做法
排序,逐位比较
代码
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <cmath>
#include <cstring>
using namespace std;
typedef long long ll;
char a[105];
int cnt[26];
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",a);
sort(a,a+strlen(a));
bool judge = true;
for(int i=1;i<strlen(a);i++)
{
if(a[i]-a[i-1]!=1)
{
judge = false;
}
}
if(judge) printf("Yes\n");
else printf("No\n");
}
}
B. Parity Alternated Deletions
题意
依次删去奇偶或偶奇直到不能再删去,问最后得到的数的和的最小值
做法
对奇偶分别计数,且排序,再对(大-小-1)求和
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
int a[3000];
int odd[3000];
int even[3000];
int main()
{
int n;
scanf("%d",&n);
int cntodd = 0;
int cnteven = 0;
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(a[i]%2==1)
{
odd[cntodd++] = a[i];
}
else
{
even[cnteven++] = a[i];
}
}
sort(odd,odd+cntodd);
sort(even,even+cnteven);
int ans = 0;
if(cntodd>cnteven)
{
for(int i=0;i<cntodd-cnteven-1;i++)
{
ans+=odd[i];
}
}
else
{
for(int i=0;i<cnteven-cntodd-1;i++)
{
ans+=even[i];
}
}
printf("%d\n",ans);
}
C. Two Shuffled Sequences
题意
给定一组数据将其拆分为严格单调增和严格单调减的两个序列
做法
统计数量,大于2直接判错,先输出一组等于2的,然后在输出大于0的(依次)
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
int a[200010];
int cnt[200010];
int main()
{
int n;
int cntt = 0;
bool judge = true;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
cnt[a[i]]++;
if(cnt[a[i]]==2) cntt++;
if(cnt[a[i]]==3) judge = false;
}
if(!judge) printf("No\n");
else
{
printf("Yes\n");
printf("%d\n",cntt);
for(int i=0;i<200010;i++)
{
if(cnt[i]==2)
printf("%d ",i);
}
printf("\n%d\n",n-cntt);
for(int i=200010;i>=0;i--)
{
if(cnt[i]>0)
printf("%d ",i);
}printf("\n");
}
}
D. Equalize Them All
题意
经过最少次题示操作使得所有数相同
做法
不难发现,1操作可使得小数等于大数,2操作可使得大数等于小数
统计出现最多的数的个数,并记录其中一个位置,从该位置分别向前和向后遍历,对每一个不等于该数的数执行一次操作
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
int a[200010];
int cnt[200010];
int main()
{
int n;
scanf("%d",&n);
int maxnum = 0;
int maxn = 0;
int sign = 0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
cnt[a[i]]++;
if(cnt[a[i]]>maxn)
{
maxn = cnt[a[i]];
maxnum = a[i];
sign = i;
}
}
printf("%d\n",n-maxn);
for(int i=sign-1;i>0;i--)
{
if(a[i]==maxnum)
{
continue;
}
else if(a[i]<maxnum)
{
printf("%d %d %d\n",1,i,i+1);
}
else
{
printf("%d %d %d\n",2,i,i+1);
}
}
for(int i=sign+1;i<=n;i++)
{
if(a[i]==maxnum)
{
continue;
}
else if(a[i]>maxnum)
{
printf("%d %d %d\n",2,i,i-1);
}
else
{
printf("%d %d %d\n",1,i,i-1);
}
}
}
E. Median String
题意
给定两个串,求其中位串(中位串指字典序排列后的中间值)
做法
26进制高精度,分别执行一次加法和除法
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
char a[200010];
char b[200010];
int c[300010];
int d[300010];
int main()
{
int n;
scanf("%d",&n);
scanf("%s",a);
scanf("%s",b);
for(int i=0;i<n;i++)
{
c[i] += a[n-1-i]+b[n-1-i]-'a'-'a';
if(c[i]>=26)
{
c[i]-=26;
c[i+1]++;
}
}
int tmp = 0;
for(int i=n;i>=0;i--)
{
d[i] =(c[i]+tmp)/2;
if(c[i]%2==0)
{
tmp=0;
}
else
{
tmp=26;
}
}
for(int i=n-1;i>=0;i--)
{
printf("%c",d[i]+'a');
}
}
F. Graph Without Long Directed Paths
题意
给无向图的边添加方向,使得图中不存在长度为二的路径
做法
每一个点只有源点或汇点两种,所以,假定一个点的种类,暴力dfs即可
代码
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
struct node
{
int u,v;
}edge[200010];
vector <int> a[200010];
int num[2000010];
bool dfs(int c,int p)
{
num[c] = p;
bool judge = true;
for(int i=0;i<a[c].size();i++)
{
if(num[a[c][i]]==-1)
{
if(!dfs(a[c][i],1-p))
{
judge = false;
}
}
else
{
if(num[a[c][i]]!=1-p) judge = false;
}
}
return judge;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
memset(num,-1,sizeof(num));
for(int i=0;i<k;i++)
{
int x,y;
scanf("%d%d",&x,&y);
edge[i].u=x;
edge[i].v=y;
a[x].push_back(y);
a[y].push_back(x);
}
if(dfs(1,0))
{
printf("Yes\n");
for(int i=0;i<k;i++)
{
printf("%d",num[edge[i].u]);
}
printf("\n");
}
else
{
printf("No\n");
}
}
G. Two Merged Sequences
题意
给定一串数字,将其不改变先后位置地分为两串,一串严格单调增,一串严格单调减
做法
如果满足要求,则每一个数必然属于下降或上升两个序列之一,对于每一个数,将它同时放在上升和下降序列的末位,若不满足条件,且另一序列中也存在该数,则将该数从序列中删去,若仍不满足,则不成立。
PS:对于两个插入,删去操作只执行一次,易证
代码
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
int a[200010];
int ans[200010];
int shangsheng[200010];
int vis1[2000010];
int xiajiang[200010];
int vis2[200010];
int main()
{
int n;
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%d",&a[i]);
}
int cntshang = 0;
int cntxia = 0;
bool judge = true;
for(int i=0; i<n; i++)
{
if(a[i]>a[shangsheng[cntshang-1]]||cntshang==0)
{
shangsheng[cntshang++] = i;
vis1[i]++;
}
else if(vis2[shangsheng[cntshang-1]]==1)
{
int tmp = shangsheng[cntshang-1];
vis1[tmp]--;
cntshang--;
if(a[i]>a[shangsheng[cntshang-1]]||cntshang==0)
{
shangsheng[cntshang++] = i;
vis1[i]++;
}
}
if(a[i]<a[xiajiang[cntxia-1]]||cntxia==0)
{
xiajiang[cntxia++] = i;
vis2[i]++;
}
else if(vis1[xiajiang[cntxia-1]]==1)
{
int tmp = xiajiang[cntxia-1];
vis2[tmp]--;
cntxia--;
if(a[i]<a[xiajiang[cntxia-1]]||cntxia==0)
{
xiajiang[cntxia++] = i;
vis2[i]++;
}
}
if(!vis1[i]&&!vis2[i])
{
judge = false;
}
if(!judge)
{
printf("NO\n");
return 0;
}
else
{
printf("YES\n");
for(int i=0; i<cntxia; i++)
{
ans[xiajiang[i]] = 1;
}
for(int i=0; i<n; i++)
{
printf("%d ",ans[i]);
}
printf("\n");
}
}