Codeforces Round #634 (Div. 3) 补题

Posted dinomax

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #634 (Div. 3) 补题相关的知识,希望对你有一定的参考价值。


A. Candies and Two Sisters
签到题,直接输出即可

代码
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	int q;
	read(q);
	while(q--){
		int n;
		read(n);
		int t=n/2;
		cout<<n-t-1<<endl;
	}
 	return 0;
}



B. Construct the String
长度a含有b个不同的字母,只要把前b个字母循环输出就好了,比赛时想麻烦了

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	int q;
	read(q);
	while(q--){
		int n,a,b;
		read(n),read(a),read(b);
		int k=a/b;
		int cnt=0;
		bool flag=true;
		for(;;){
			for(int i=0;i<b;i++){
				for(int j=0;j<k;j++){
					putchar(‘a‘+i);
					if(++cnt==n){
						flag=false;
						break;
					}
				}
				if(!flag) break;
			}
			if(!flag) break;
		}
		putchar(‘
‘);
	}
 	return 0;
}



C. Two Teams Composing
统计出每种元素的个数,并记录所有元素中的最大个数。如果个数最多的元素为x,那么两个队列有两种构造方式:第一队不包含x,第二队全为x;第一队包含x,第二队全为x,比较这两种构造方式的结果的最大值即可。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
map<int,int> a;
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	int q;
	read(q);
	while(q--){
		int n;
		int m=0;
		int sum=0;
		read(n);
		//map<int,int> a;
		a.clear();
		for(int i=0;i<n;i++){
			int t;
			read(t);
			if(!a[t]) sum++;
			a[t]++;
			m=max(m,a[t]); 
		}
		cout<<max(min(sum-1,m),min(sum,m-1))<<"
";
	}
 	return 0;
}



D. Anti-Sudoku
我的想法是九个小的格子中每个格子一定要改变一个数,让改变的数可以影响一行一列,最后让九个数影响的行和列不同就行了。对于不同的数独,改变的位置可以是固定的,改变的方法可以是让这个数加一。
答案给的方法很巧妙,让数独中所有的某个数变成其他数就好了,比如所有2都变成1

代码
#define LOCAL0
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
vector<vector<int> > a(10,vector<int>(10)); 
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	int q;
	read(q);
	while(q--){
		char s;
		for(int i=1;i<=9;i++)
			for(int j=1;j<=9;j++){
				cin>>s;
				a[i][j]=s-‘1‘;
			}
		a[1][1]=(a[1][1]+1)%9;
		a[2][5]=(a[2][5]+1)%9;
		a[3][9]=(a[3][9]+1)%9;
		
		a[5][2]=(a[5][2]+1)%9;
		a[6][6]=(a[6][6]+1)%9;
		a[4][7]=(a[4][7]+1)%9;

		a[9][3]=(a[9][3]+1)%9;
		a[7][4]=(a[7][4]+1)%9;
		a[8][8]=(a[8][8]+1)%9;

		for(int i=1;i<=9;i++)
		{
			for(int j=1;j<=9;j++)
				printf("%d",a[i][j]+1);
			putchar(‘
‘);
		}
	}
 	return 0;
}



E1. Three Blocks Palindrome (easy version)
比赛时只想到了E1的解法,还交了八次才过。。。
我的想法是对每一种元素都维护一次前缀和(个数),这样就能方便的得出每种元素在某一区间内的数量。题目要求的数列是分为三部分,我的做法是固定中间的那部分,再遍历两边元素的最大数目,因为是固定中间部分的左边界l和右边界r,遍历l和r的复杂度是n2。

代码

#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
//map<int,int> idx;
int sum[30][3000];
int idx[300];
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	int q;
	read(q);
	while(q--){
		int n,cnt=0,ans=0;
		read(n);
		memset(idx,0,sizeof(idx));
		memset(sum,0,sizeof(sum));
		for(int i=1;i<=n;i++){
			int v;
			read(v);
			if(!idx[v]) idx[v]=++cnt;
			for(int j=1;j<=cnt;j++){
				sum[j][i]=sum[j][i-1];
				if(idx[v]==j) sum[j][i]++;
			}
		}
			
		for(int l=1;l<=n;l++)
			for(int r=l;r<=n;r++){
				for(int i=1;i<=cnt;i++)
					for(int j=1;j<=cnt;j++){
						//if(l!=1&&j==i) continue;
						ans=max(ans,sum[i][r]-sum[i][l-1]+2*min(sum[j][n]-sum[j][r],sum[j][l-1]));
						//cout<<l<<" "<<r<<" "<<ans<<endl;
					}
			}
		for(int i=1;i<=cnt;i++) ans=max(ans,sum[cnt][n]);
		cout<<ans<<"
";
	}
 	return 0;
}
 

E2. Three Blocks Palindrome (hard version)
其实标程前半部分也是维护前缀数目,但是后面在求解的时候是相当于固定两边,遍历中间的部分,预处理时要统计每种元素出现的位置。求解时按照元素遍历,先统计这种元素在[1,n]上的数目,再把这种元素左右各取c个,就可以得到中间部分左右端的位置。

代码
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
int sum[30][3000];
int idx[300];
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	int q;
	read(q);
	while(q--){
		int n;
		read(n);
		vector<int> a(n+1);
		vector<vector<int> > pref(201,vector<int>(n+1));
		vector<vector<int> > pos(201);
		for(int i=1;i<=n;i++) read(a[i]);
		for(int i=1;i<=n;i++){
			for(int j=1;j<=200;j++) pref[j][i]=pref[j][i-1];
			pref[a[i]][i]++;
			pos[a[i]].push_back(i);
		}
		int ans=0;
		for(int i=1;i<=200;i++){
			int u=pos[i].size();
			ans=max(ans,u);
			for(int j=1;2*j<=u;j++){
				int l=pos[i][j-1];
				int r=pos[i][u-j];
				for(int k=1;k<=200;k++){
					if(k==i) continue;
					ans=max(ans,2*j+pref[k][r-1]-pref[k][l]);
				}
			}
		}
		cout<<ans<<"
";
	}
 	return 0;
}
 

F. Robots on a Grid
首先所给图中是由一些环组成的,否则机器人会一直走到没走过的点,而图的大小是有限的。如果两个机器人在某一时刻相遇,那么他们之后会一起走,就是题中的不允许的条件,因为环的最大周期不超过n*m,所以只要两个机器人在n*m步内没有相遇,那么他们就不可能相遇。统计每个格子上的机器人n*m步之后会在哪,之后就能得到n*m步之后有几个格子上的机器人能走到某一格,以及几个黑格子上的机器人能走到某个黑格子,就能方便的统计答案,让每个格子上的机器人走n*m步显然会超时,所以采用倍增的方法。

代码
#include <iostream>
#include<vector>
#include<map>
#include<queue>
#include<set>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
#include<stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
using namespace std;
inline void read(int &p)
{
    p=0;int flag=1;char c=getchar();
    while(!isdigit(c)) {if(c==‘-‘) flag=-1;c=getchar();}
    while(isdigit(c)) {p=p*10+c-‘0‘;c=getchar();}p*=flag;
}
int sum[30][3000];
int idx[300];
int main()
{
	#ifdef LOCAL
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif
	int q;
	read(q);
	while(q--){
		int n,m;
		read(n),read(m);
		vector<int> col(n*m),dp(n*m),dpn(n*m),ans(n*m),co(n*m);
		string s;
		for(int i=0;i<n;i++){
			cin>>s;
			for(int j=0;j<m;j++){
				col[i*m+j]=(s[j]==‘0‘);
			}
		}
		for(int i=0;i<n;i++){
			cin>>s;
			for(int j=0;j<m;j++){
				int nxt=-1;
				if(s[j]==‘U‘) nxt=(i-1)*m+j;
				if(s[j]==‘D‘) nxt=(i+1)*m+j;
				if(s[j]==‘L‘) nxt=i*m+j-1;
				if(s[j]==‘R‘) nxt=i*m+j+1;
				dp[i*m+j]=nxt;
			}
		}
		int k=0;
		n*=m;
		while((1<<k)<=n) k++;
		while(k--){
			for(int i=0;i<n;i++){
				dpn[i]=dp[dp[i]];
			}
			for(int i=0;i<n;i++){
				dp[i]=dpn[i];
			}
		}
		for(int i=0;i<n;i++){
			ans[dp[i]]++;
			co[dp[i]]+=col[i];
		}
		int res=0,_res=0;
		for(int i=0;i<n;i++){
			if(ans[i]) res++;
			if(co[i]) _res++;
		}
		cout<<res<<" "<<_res<<"
";
	}
 	return 0;
}
 

以上是关于Codeforces Round #634 (Div. 3) 补题的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #634 (Div. 3)

Codeforces Round #634 (Div. 3)

Codeforces Round #634 D. Anti-Sudoku(构造/水)

Codeforces Round #436 E. Fire(背包dp+输出路径)

[ACM]Codeforces Round #534 (Div. 2)

codeforces #634(div3) A-E题解