题解 - Codeforces Round #634 (Div. 3,完整版)

C o d e f o r c e s   R o u n d   634   ( D i v . 3 ) \mathrm{Codeforces\ Round \ 634 \ (Div. 3) } 完整题解

A .   C a n d i e s   a n d   T w o   S i s t e r s \mathrm{A.\ Candies \ and \ Two \ Sisters}

题目意思

S o l \mathrm{Sol}

  • 一眼啊。直接输出 2 n \left\lfloor\dfrac{2}{n}\right\rfloor 就可以了

C o d e \mathrm{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 .   C o n s t r u c t   t h e   S t r i n g \mathrm{B.\ Construct \ the \ String}

题目意思

S o l \mathrm{Sol}

  • 又是一眼题。只要循环输出就可以了(题目中的 a a 没啥用)不理解看一下代码。
  • 比如 n = 7 , a = 5 , b = 3 n=7,a=5,b=3 那么只要构造: a b c   a b c   a abc\ abc\ a 就可以了

C o d e \mathrm{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 .   T w o   T e a m s   C o m p o s i n g \mathrm{C.\ Two \ Teams \ Composing}

题目意思

S o l \mathrm{Sol}

  • 我们只要统计每个能力出现的次数
  • 找出出现次数最多的数,设其出现次数为 a a
  • 统计除去这个数有多少个不同的数,设为 b b
  • 则每组人数可为 min { a , b } \min\{a,b\} 。当 a 2 a 2 a\geq 2a≥2 时,还可把出现次数最多的数分到第一组,答案为 min ( a 1 , b + 1 ) \min(a-1,b+1)

C o d e \mathrm{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 .   A n t i S u d o k u \mathrm{D.\ Anti-Sudoku}

题目意思

S o l \mathrm{Sol}

  • 谔谔题:只要把矩形里的 1 1 变为 2 2 就可以了

C o d e \mathrm{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;
}

E 1 , E 2.   T h r e e   B l o c k s   P a l i n d r o m e \mathrm{E1,E2.\ Three \ Blocks\ Palindrome }

题目意思

S o l \mathrm{Sol}

  • 比较简单的模拟题
  • 首先我们记录某一个数 a i a_i i i 出现的次数以及出现到这个次数的位置。前缀后缀个各做一遍。
  • 然后我们枚举第一个颜色 x x 以及它第一段的长度 l l 。然后得出 p 1 , p 2 p_1,p_2 分别表示前缀 x x 颜色到达 l l 个的位置,以及后缀到达 l l 个的位置。然后在枚举第二种颜色 y y ,那么 a n s = max ( a n s , l × 2 + max c o l s u m ( p 2 p 1 ) ) ans=\max(ans,l\times 2+\max_{colsum}(p_2-p_1)) , max c o l s u m ( p 2 p 1 ) \max_{colsum}(p_2-p_1) 为到 [ p 1 , p 2 ] [p1,p2] 这段区间里面出现次数最多的颜色数量。

S o l \mathrm{Sol}

  • 写法 1 1
#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;
}
  • 写法 2 2 建图优化内存
#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 .   R o b o t s   o n   a   G r i d \mathrm{F.\ Robots \ on \ a \ Grid }

题目意思

S o l \mathrm{Sol}

  • 这场比赛唯一比较难的题目。
  • 首先每个点只有 1 1 条出边(每个点之间按方向连边)构成了一个基环内向树森林
  • 那么我们就枚举每个环,以环上某一个点 x x 割断与他的父亲 f x f_x 的边然后再 d f s dfs 一遍求出环内每个点的深度,以及环长。如果一个环内不存在任意两点为同一个深度那么这两个点都是可以选的。然后分白块黑块各自计数器加加就可以了。
  • 注意把所有数组清空,不要使用 m e m s e t memset T L E TLE 不管我

C o d e \mathrm{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];
				}
//				cout<<"root="<<x<<endl;
				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;
}
						

猜你喜欢

转载自blog.csdn.net/wangyiyang2/article/details/105507851