Codeforces Round 634 (Div.3) 完整题解
A. Candies and Two Sisters
题目意思
Sol
- 一眼啊。直接输出
⌊n2⌋ 就可以了
Code
#include <bits/stdc++.h>
#define pb push_back
#define int long long
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
signed main()
{
int Q=read();
for (;Q--;)
{
int n=read();
printf("%lld\n",(n-1)/2);
}
}
B. Construct the String
题目意思
Sol
- 又是一眼题。只要循环输出就可以了(题目中的
a没啥用)不理解看一下代码。
- 比如
n=7,a=5,b=3那么只要构造:
abc abc a就可以了
Code
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
int main()
{
int Q=read();
for (;Q--;)
{
int x,y,z;
x=read();
y=read();
z=read();
for ( int i=1,j=0;i<=x;i++,j=(j+1)%z) putchar('a'+j);
puts("");
}
return 0;
}
C. Two Teams Composing
题目意思
Sol
- 我们只要统计每个能力出现的次数
- 找出出现次数最多的数,设其出现次数为
a
- 统计除去这个数有多少个不同的数,设为
b
- 则每组人数可为
min{a,b}。当
a≥2a≥2 时,还可把出现次数最多的数分到第一组,答案为
min(a−1,b+1)。
Code
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
int a[1000005];
int main()
{
int T=read();
for(;T--;)
{
int n=read();
for( int i=1;i<=n;i++ ) a[i]=0;
for( int i=1;i<=n;i++ ) a[read()]++;
int gs=0,ans=0;
for( int i=1;i<=n;i++ )
if(a[i]>0) gs++;
for( int i=1;i<=n;i++ )
if(a[i])
{
ans=max(ans,min(gs-1,a[i]));
ans=max(ans,min(gs,a[i]-1));
}
printf("%d\n",ans);
}
return 0;
}
D. Anti−Sudoku
题目意思
Sol
- 谔谔题:只要把矩形里的
1变为
2就可以了
Code
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
int a[11][11];
int main()
{
int Q=read();
for ( int i=1;i<=Q;i++ )
{
for ( int j=1;j<=9;j++ )
for ( int k=1;k<=9;k++ )
{
scanf("%1d",&a[j][k]);
if(a[j][k]==1) a[j][k]++;
}
for ( int j=1;j<=9;j++ )
{
for ( int k=1;k<=9;k++ )
printf("%d",a[j][k]);
puts("");
}
}
return 0;
}
E1,E2. Three Blocks Palindrome
题目意思
Sol
- 比较简单的模拟题
- 首先我们记录某一个数
ai到
i出现的次数以及出现到这个次数的位置。前缀后缀个各做一遍。
- 然后我们枚举第一个颜色
x以及它第一段的长度
l。然后得出
p1,p2分别表示前缀
x颜色到达
l个的位置,以及后缀到达
l个的位置。然后在枚举第二种颜色
y,那么
ans=max(ans,l×2+maxcolsum(p2−p1)),
maxcolsum(p2−p1)为到
[p1,p2]这段区间里面出现次数最多的颜色数量。
Sol
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
const int N=2005;
int n,m,f[N][205],g[N][205],a[N],pre[205][N],suf[205][N],ans;
int main()
{
int Q=read();
for (;Q--;)
{
n=read();
for ( int i=1;i<=n;i++ )
{
a[i]=read();
for ( int j=1;j<=200;j++ ) f[i][j]=f[i-1][j];
f[i][a[i]]++;
pre[a[i]][f[i][a[i]]]=i;
}
for ( int i=n;i>=1;i-- )
{
for ( int j=1;j<=200;j++ ) g[i][j]=g[i+1][j];
g[i][a[i]]++;
suf[a[i]][g[i][a[i]]]=i;
}
for ( int i=1;i<=200;i++ )
{
for ( int j=1;j<=f[n][i]/2;j++ )
{
int pos1=pre[i][j];
int pos2=suf[i][j];
if(pos1>pos2) continue;
for ( int k=1;k<=200;k++ )
{
if(k==i) continue;
ans=max(ans,j*2+f[pos2][k]-f[pos1][k]);
}
}
ans=max(ans,f[n][i]);
}
printf("%d\n",ans);
ans=0;
memset(pre,0,sizeof(pre));memset(suf,0,sizeof(suf));
memset(f,0,sizeof(pre));memset(g,0,sizeof(suf));
}
return 0;
}
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
const int N=2e5+5;
int n,m,ans,f[N][205],TT,a[N],l[N],head[N];
struct nood
{
int nex,to;
};
nood e[N];
inline void jia(int u,int v)
{
e[++TT].nex=head[u];
head[u]=TT;
e[TT].to=v;
}
int main()
{
int Q=read();
for (;Q--;)
{
n=read();
for ( int i=1;i<=200;i++ ) head[i]=0;
TT=0;
for ( int i=1;i<=n;i++ )
{
a[i]=read();
jia(a[i],i);
for ( int j=1;j<=200;j++ )
f[i][j]=f[i-1][j];
f[i][a[i]]++;
}
int ans=1;
for ( int k=1;k<=200;k++ )
{
int cnt=0;
for ( int p=head[k];p;p=e[p].nex )
{
int v=e[p].to;
l[++cnt]=v;
}
int p=cnt/2;
for ( int i=1;i<=p;i++ )
{
int mx=0;
for ( int j=1;j<=200;j++ )
mx=max(mx,f[l[i]-1][j]-f[l[cnt-i+1]][j]);
ans=max(ans,mx+i*2);
}
}
printf("%d\n",ans);
}
return 0;
}
F. Robots on a Grid
题目意思
Sol
- 这场比赛唯一比较难的题目。
- 首先每个点只有
1条出边(每个点之间按方向连边)构成了一个基环内向树森林
- 那么我们就枚举每个环,以环上某一个点
x割断与他的父亲
fx的边然后再
dfs一遍求出环内每个点的深度,以及环长。如果一个环内不存在任意两点为同一个深度那么这两个点都是可以选的。然后分白块黑块各自计数器加加就可以了。
- 注意把所有数组清空,不要使用
memset,
TLE不管我
Code
#include <bits/stdc++.h>
#define pb push_back
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
const int N=1e6+5;
int n,m,f[N],pd1[N],pd2[N],ct0[N],ct1[N],vis[N];
int ans1,ans2,col[N],head[N],dep[N],cnt,MD;
char ch[N];
struct nood
{
int nex,to;
};
nood e[N];
inline void jia(int u,int v)
{
e[++cnt].nex=head[u];
head[u]=cnt;
e[cnt].to=v;
}
inline int id(int x,int y)
{
return (x-1)*m+y;
}
inline void dfs(int u,int fa,int rt)
{
if(col[u]) ct1[dep[u]]++;
else ct0[dep[u]]++;
MD=max(MD,dep[u]);
vis[u]=1;
for ( int i=head[u];i;i=e[i].nex )
{
int v=e[i].to;
if(v==rt||v==fa) continue;
dep[v]=dep[u]+1;
dfs(v,u,rt);
}
}
int main()
{
int Q=read();
for (;Q--;)
{
n=read();
m=read();
int all=n*m;
for ( int i=1;i<=n;i++ )
{
scanf("%s",ch+1);
for ( int j=1;j<=m;j++ )
{
if(!(ch[j]^48))
col[id(i,j)]=0;
else
col[id(i,j)]=1;
}
}
for ( int i=1;i<=n;i++ )
{
scanf("%s",ch+1);
for ( int j=1;j<=m;j++ )
{
if(ch[j]=='R')
f[id(i,j)]=id(i,j+1);
if(ch[j]=='L')
f[id(i,j)]=id(i,j-1);
if(ch[j]=='U')
f[id(i,j)]=id(i-1,j);
if(ch[j]=='D')
f[id(i,j)]=id(i+1,j);
}
}
cnt=0;
for ( int i=1;i<=all;i++ ) head[i]=0;
for ( int i=1;i<=all;i++ ) jia(f[i],i);
for ( int i=1;i<=all;i++ )
if(!vis[i])
{
int x=i;
while(!vis[x])
{
vis[x]=1;
x=f[x];
}
dep[x]=0,MD=0;
dfs(x,0,x);
int huan=dep[f[x]]+1;
for ( int j=0;j<=MD;j++ )
{
if(ct0[j])
{
pd1[j%huan]=1;
pd2[j%huan]=1;
}
else
if(ct1[j])
pd1[j%huan]=1;
}
for ( int j=0;j<huan;j++ )
{
ans1+=pd1[j];
ans2+=pd2[j];
}
for ( int j=0;j<=MD;j++ )
{
pd1[j]=pd2[j]=ct0[j]=ct1[j]=0;
}
}
for ( int i=1;i<=all;i++ ) vis[i]=0;
printf("%d %d\n",ans1,ans2);
ans1=ans2=0;
}
return 0;
}