tozangezan's diary

勝手にソースコードをコピペして利用しないでください。

Codeforces Round #381 (Div. 1)

Dが難しすぎてCがクソゲー。レッドコーダー的にはつまらないセット。

A B C D E Place
00:03 00:18 01:42 (+1) - - 51st

A:
簡単すぎて逆に焦るやつ

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int main(){
	int a,b;scanf("%d%d",&a,&b);
	int ans=9999999;
	for(int i=0;i<b;i++){
		int p,q;scanf("%d%d",&p,&q);
		ans=min(ans,q-p+1);
	}
	printf("%d\n",ans);
	for(int i=0;i<a;i++){
		if(i)printf(" ");
		printf("%d",i%ans);
	}
	printf("\n");
}

B:
木をDFSしたときにd[深さ]=距離みたいな配列にすると、どこまでいけるか二分探索できる。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int c[210000];
vector<pair<int,int> >g[210000];
long long tmp[210000];
int par[210000];
int ans[210000];
void dfs(int a,int b){
	for(int i=0;i<g[a].size();i++){
		tmp[b+1]=tmp[b]+g[a][i].second;
		par[b+1]=g[a][i].first;
		dfs(g[a][i].first,b+1);
		ans[a]+=ans[g[a][i].first];
	}
	long long L=tmp[b]-c[a];
	int at=lower_bound(tmp,tmp+b+1,L)-tmp;
	ans[a]++;
	if(at)ans[par[at-1]]--;
}
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++)scanf("%d",c+i);
	for(int i=0;i<a-1;i++){
		int p,q;scanf("%d%d",&p,&q);
		p--;
		g[p].push_back(make_pair(i+1,q));
	}
	dfs(0,0);
	for(int i=0;i<a;i++){
		if(i)printf(" ");
		printf("%d",ans[i]-1);
	}
	printf("\n");
}

C:
setで範囲を持って頑張って更新するだけ。何が面白いのかさっぱりわからない上、(こういう明らかに定数つきそうな問題のくせして)定数倍がきつくpretest後に落ちる。時々writerが犯す、コンテストを機械的に難しくするミスの一種。本番出てなくてよかった。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int f[310000];
long long c[310000];
int segtree[1048576];
int query(int a,int b,int c,int d,int e){
	if(d<a||b<c)return 0;
	if(c<=a&&b<=d)return segtree[e];
	return max(query(a,(a+b)/2,c,d,e*2),query((a+b)/2+1,b,c,d,e*2+1));
}
void update(int a,int b){
	a+=524288;
	segtree[a]=b;
	a/=2;
	while(a){
		segtree[a]=max(segtree[a*2],segtree[a*2+1]);
		a/=2;
	}
}
set<pair<pair<int,int>,int> >S;
set<pair<int,int> >T;
set<pair<int,int> >Tinv;
typedef set<pair<pair<int,int>,int> >::iterator wolf;
inline int sig(long long a){
	if(a<0)return -1;
	if(a==0)return 0;
	return 1;
}
int n;
void add(int a,int b){
	int sc=sig(c[a]);
	int tc=sig(c[a]+b);
	c[a]+=b;
	if(sc==tc)return;
	wolf it=S.upper_bound(make_pair(make_pair(a,mod),0));
	it--;
	pair<pair<int,int>,int> p=(*it);
	if(p.first.first<a)S.insert(make_pair(make_pair(p.first.first,a),sc));
	S.insert(make_pair(make_pair(a,a+1),tc));
	if(a+1<p.first.second)S.insert(make_pair(make_pair(a+1,p.first.second),sc));
	S.erase(p);

	wolf it2=S.upper_bound(make_pair(make_pair(p.first.first-1,mod),0));
	if(it2!=S.begin())it2--;
	if(it2!=S.begin())it2--;
	

	vector<pair<pair<int,int>,int> >que;
	vector<pair<int,int> > del2;

	for(;it2!=S.end()&&(*it2).first.first<=a+1;it2++){
		que.push_back(*it2);
	}
	int last=0;
	int len=0;
	int col=-2;
	vector<pair<pair<int,int>,int> >del;
	for(int i=0;i<que.size();i++){
		update(que[i].first.first,0);
		if(que[i].second!=col){
			if(col!=-2&&len>1){
				S.insert(make_pair(make_pair(last,que[i].first.first),col));
				for(int j=0;j<del.size();j++)S.erase(del[j]);
			}
			del.clear();
			len=0;
			last=que[i].first.first;
			col=que[i].second;
		}
		del.push_back(que[i]);
		len++;
	}
	if(len>1){
		S.insert(make_pair(make_pair(last,que[que.size()-1].first.second),col));
		for(int j=0;j<del.size();j++)S.erase(del[j]);
	}
	
	wolf it4=S.lower_bound(make_pair(make_pair(que[0].first.first,0),-mod));
	for(;it4!=S.end()&&(*it4).first.first<=a+1;it4++){
		pair<pair<int,int>,int>  d=(*it4);
		if(d.second==0)continue;
		int le=d.first.second-d.first.first;
		if(d.second==1){
			it4++;
			if(d.first.second<n-1&&(*it4).second==-1)le+=(*it4).first.second-(*it4).first.first;
			it4--;
		}
//		T.insert(make_pair(le,d.first.first));
//		Tinv.insert(make_pair(d.first.first,le));
		update(d.first.first,le);
	}
//	for(wolf i=S.begin();i!=S.end();i++)printf("%d %d: %d\n",(*i).first.first,(*i).first.second,(*i).second);
	//for(int i=0;i<n;i++)printf("%d ",segtree[524288+i]);
	//printf("\n");
}

int main(){
	int a;scanf("%d",&a);
	n=a;
	for(int i=0;i<a;i++)scanf("%d",f+i);
	if(a==1){
		int q;scanf("%d",&q);
		while(q--)printf("1\n");return 0;
	}
	for(int i=0;i<a-1;i++)c[i]=f[i+1]-f[i];
	int len=0;
	int cur=-2;
	for(int i=0;i<a-1;i++){
		int v=sig(c[i]);
		if(v!=cur){
			if(len)S.insert(make_pair(make_pair(i-len,i),cur));
			len=0;cur=v;
		}
		len++;
	}
	S.insert(make_pair(make_pair(a-1-len,a-1),cur));
	for(wolf it=S.begin();it!=S.end();it++){
		if((*it).second==0)continue;
		if((*it).second==1){
			int le=(*it).first.second-(*it).first.first;
			wolf tmp=it;
			tmp++;
			if(tmp!=S.end()&&(*tmp).second==-1)le+=(*tmp).first.second-(*tmp).first.first;
	//		T.insert(make_pair(le,(*it).first.first));
	//		Tinv.insert(make_pair((*it).first.first,le));
			update((*it).first.first,le);
		}else{
	//		T.insert(make_pair((*it).first.second-(*it).first.first,(*it).first.first));
	//		Tinv.insert(make_pair((*it).first.first,(*it).first.second-(*it).first.first));	
			update((*it).first.first,(*it).first.second-(*it).first.first);
		}
	}
	int Q;scanf("%d",&Q);
	while(Q--){
		int p,q,r;scanf("%d%d%d",&p,&q,&r);
		p--;
		if(p>=1)add(p-1,r);
		if(q<a)add(q-1,-r);
		printf("%d\n",segtree[1]+1);
	}
}

D:
時間がなくて全然考えてないけど (p,?) と (?,q) の割り当て問題? また今度。これも復元が無駄に付いてる気がするんだけど......。

Codeforces Round #382 (Div. 1)

結果もあれだがひどいセット。

A B C D E Place
00:09 (+1) 00:16 01:02 (+1) (-1) - 57th

A:
Fibonnacci heapのあの図みたいな配置。2^nではない。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int main(){
	long long a;scanf("%I64d",&a);
	int ret=0;
	while(a>1){
		ret++;a=(a+1)/2;
	}
	printf("%d\n",ret);
}

B:
ゴールドバッハから偶数の答えの最大は2。奇数は3引けば同様に最大3。あとは素数判定で場合分け。
プログラミングとは

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
bool pr(int a){
	for(int i=2;i*i<=a;i++){
		if(a%i==0)return false;
	}
	return true;
}
int main(){
	int a;scanf("%d",&a);
	if(a%2==0){
		if(a==2)printf("1\n");
		else printf("2\n");return 0;
	}
	if(pr(a))printf("1\n");
	else if(pr(a-2))printf("2\n");
	else printf("3\n");
}

C:
このセットでは珍しくプログラミング要素だが、ただ遷移が複雑でつらいだけの木DP。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int K;
long long dp[110][23][23];
vector<int>g[110];
long long dp2[110][23][23];
void calc(int a,int b){
	for(int i=0;i<g[a].size();i++){
		if(b==g[a][i])continue;
		calc(g[a][i],a);
	}
	int t=0;
	for(int i=0;i<110;i++)for(int j=0;j<23;j++)for(int k=0;k<23;k++)dp2[i][j][k]=0;
	dp2[0][K+1][1]=1;
	dp2[0][0][0]=1;
	
	for(int i=0;i<g[a].size();i++){
		if(b==g[a][i])continue;
		for(int j=0;j<=K+1;j++){
			for(int k=0;k<=K;k++){
				if(!dp2[t][j][k])continue;
				for(int l=0;l<=K+1;l++)for(int m=0;m<=K;m++){
					if(!dp[g[a][i]][l][m])continue;
					int tj=j;int tk=k;
					tj=min(tj,l+1);
					if(tj+k-1<=K)tk=0;
					if(m&&tj+m>K)tk=max(tk,m+1);
					dp2[t+1][tj][tk]=(dp2[t+1][tj][tk]+dp2[t][j][k]*dp[g[a][i]][l][m])%mod;
				}
			}
		}
		t++;
	}
	/*for(int j=0;j<=K+1;j++){
		for(int k=0;k<=K;k++){
			int tj=j;int tk=k;
			if(tj==K+1)tk++;
			dp2[t+1][tj][tk]=(dp2[t+1][tj][tk]+dp2[t][j][k])%mod;
			dp2[t+1][0][0]=(dp2[t+1][0][0]+dp2[t][j][k])%mod;
		}
	}
	t++;*/
	for(int i=0;i<=K+1;i++)for(int j=0;j<=K;j++)dp[a][i][j]=dp2[t][i][j];
//	for(int i=0;i<=K+1;i++)for(int j=0;j<=K;j++){
//		if(dp[a][i][j])printf("%d %d %d: %I64d\n",a,i,j,dp[a][i][j]);
//	}
}
int main(){
	int a,b;scanf("%d%d",&a,&b);
	K=b;
	for(int i=0;i<a-1;i++){
		int p,q;scanf("%d%d",&p,&q);p--;q--;
		g[p].push_back(q);
		g[q].push_back(p);
	}
	calc(0,-1);
	long long ret=0;
	for(int i=0;i<=K+1;i++)ret=(ret+dp[0][i][0])%mod;
	printf("%I64d\n",ret);
}

D:
permutationの個数の偶奇は行列式の偶奇。1要素ずつ取り除いたものを転置してできる行列は余因子行列。余因子行列は、det(A)が奇数なので実質逆行列と同じ。よってビット並列で逆行列を求めるだけ。
プログラミング要素、0。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int c[2100][4100];
int s[2100];
int t[2100];
int ans[510000];
typedef unsigned long long wolf;
wolf mat[2100][65];
int D=64;
int x[510000];
int y[510000];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<b;i++){
		int p,q;scanf("%d%d",&p,&q);p--;q--;
		c[p][q]=1;
		x[i]=p;y[i]=q;
	}
	for(int i=0;i<a;i++)for(int j=0;j<a*2;j++){
		if(c[i][j]||j==i+a)mat[i][j/D]+=(1LL<<(j%D));
	}
	int cur=0;
	for(int i=0;i<a;i++){
		int at=-1;
		for(int j=cur;j<a;j++){
			if(mat[j][i/D]&(1LL<<(i%D))){
				at=j;break;
			}
		}
		if(!~at)continue;
		for(int k=0;k<65;k++)swap(mat[at][k],mat[cur][k]);
		for(int j=0;j<a;j++){
			if(cur==j)continue;
			if(mat[j][i/D]&(1LL<<(i%D))){
				for(int k=0;k<65;k++)mat[j][k]^=mat[cur][k];
			}
		}

		cur++;
	}
	for(int i=0;i<b;i++){
		if(mat[y[i]][(a+x[i])/D]&(1LL<<((a+x[i])%D)))printf("NO\n");
		else printf("YES\n");
	}
}

Codeforces Round #383 (Div. 1)

A B C D E Place
00:06 00:14 01:03 (+1) (-2) - 35th

悪くはないと思うんだけどね......

A:
サイクルさがしてLCM.

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int b[110];
long long gcd(long long a,long long b){
	while(a){
		b%=a;swap(a,b);
	}
	return b;
}
long long lcm(long long a,long long b){
	return a/gcd(a,b)*b;
}
int v[110];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++)scanf("%d",b+i);
	for(int i=0;i<a;i++)b[i]--;
	long long ret=1;
	for(int i=0;i<a;i++){
		if(v[i])continue;
		int at=i;
		v[at]=1;
		int cnt=0;
		while(1){
			at=b[at];
			cnt++;
			if(v[at]){
				if(at==i)break;
				else{
					printf("-1\n");return 0;
				}
			}
			v[at]=1;
		}
		if(cnt%2==0)cnt/=2;
		ret=lcm(ret,cnt);
	}
	printf("%I64d\n",ret);
}

B:
こんなやるだけ典型もういらないから

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int UF[1100];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);if(a==b)return;UF[a]+=UF[b];UF[b]=a;
}
vector<int>v[1100];
int p[1100];
int q[1100];
int dp[1100][1100];
int main(){
	int a,b,c;scanf("%d%d%d",&a,&b,&c);
	for(int i=0;i<a;i++){
		scanf("%d",p+i);
	}
	for(int i=0;i<a;i++){
		scanf("%d",q+i);
	}
	for(int i=0;i<a;i++)UF[i]=-1;
	for(int i=0;i<b;i++){
		int s,t;scanf("%d%d",&s,&t);s--;t--;UNION(s,t);
	}
	for(int i=0;i<a;i++){
		v[FIND(i)].push_back(i);
	}
	for(int i=0;i<1100;i++)for(int j=0;j<1100;j++)dp[i][j]=-mod;
	dp[0][0]=0;
	for(int i=0;i<a;i++){
		int W=0;
		int B=0;
		for(int j=0;j<v[i].size();j++){
			W+=p[v[i][j]];
			B+=q[v[i][j]];
		}
		for(int j=0;j<=c;j++){
			dp[i+1][j]=max(dp[i+1][j],dp[i][j]);
			if(j+W<=c)dp[i+1][j+W]=max(dp[i+1][j+W],dp[i][j]+B);
			for(int k=0;k<v[i].size();k++){
				if(j+p[v[i][k]]<=c)dp[i+1][j+p[v[i][k]]]=max(dp[i+1][j+p[v[i][k]]],dp[i][j]+q[v[i][k]]);
			}
		}
	}
	int ret=0;
	for(int i=0;i<=c;i++)ret=max(ret,dp[a][i]);
	printf("%d\n",ret);
}

C:
一発ネタ。「偶数と奇数は別の色」に制約を強める(これは真に強い)と途端に簡単になる。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int UF[410000];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);if(a==b)return;UF[a]+=UF[b];UF[b]=a;
}
int A[110000];
int B[110000];
int ans[410000];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<4*a;i++)UF[i]=-1;
	int F=a*2;
	for(int i=0;i<a;i++){
		UNION(i*2,i*2+1+F);
		UNION(i*2+F,i*2+1);
	}
	for(int i=0;i<a;i++){
		int p,q;scanf("%d%d",&p,&q);p--;q--;
		A[i]=p;B[i]=q;
		UNION(p,q+F);
		UNION(q,p+F);
	}
	for(int i=0;i<4*a;i++)ans[i]=-1;
	for(int i=0;i<a;i++){
		int f=ans[FIND(A[i])];
		if(f<0){
			ans[FIND(A[i])]=0;
			ans[FIND(A[i]+F)]=1;
			f=0;
		}
		printf("%d %d\n",f+1,(!f)+1);
	}
}

D:
dsuというCFでは頻出のアルゴリズムらしい。慣れてないアルゴリズムは実装しててもどこが悪いのかわからなくて嵌り続ける。
結局部分木のサイズを計算するのが間違っていた......

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
vector<pair<int,char> >g[510000];
char in[510000];
int ans[510000];
int dep[510000];
int sz[510000];
int key[510000];
void dfs(int a){
	sz[a]=1;
	for(int i=0;i<g[a].size();i++){
		dep[g[a][i].first]=dep[a]+1;
		key[g[a][i].first]=key[a]^(1<<(g[a][i].second-'a'));
		dfs(g[a][i].first);
		
		sz[a]+=sz[g[a][i].first];
	}
}
int wolf[1<<22];
vector<int>del;
vector<int>vis;
void dfs2(int a,int b){
	for(int i=0;i<g[a].size();i++){
		dfs2(g[a][i].first,b);
	}
	for(int k=0;k<23;k++){
		int x=key[a];
		if(k<22)x^=(1<<k);
		ans[b]=max(ans[b],dep[a]+wolf[x]-2*dep[b]);
	}
}
void dfs3(int a){
	for(int i=0;i<g[a].size();i++){
		dfs3(g[a][i].first);
	}
	if(wolf[key[a]]<0)del.push_back(key[a]);
	wolf[key[a]]=max(wolf[key[a]],dep[a]);
}
void calc(int a){
	int lc=-1;
	int val=-1;
	for(int i=0;i<g[a].size();i++){
		if(val<sz[g[a][i].first]){
			lc=g[a][i].first;
			val=sz[g[a][i].first];
		}
	}
	for(int i=0;i<g[a].size();i++){
		if(g[a][i].first==lc)continue;
		calc(g[a][i].first);
		for(int j=0;j<del.size();j++){
			wolf[del[j]]=-mod;
		}
		del.clear();
	}
	if(~lc){
		calc(lc);
		for(int i=0;i<g[a].size();i++){
			if(g[a][i].first!=lc){
				dfs2(g[a][i].first,a);
				dfs3(g[a][i].first);
			}
		}
	}
	for(int i=0;i<23;i++){
		int x=key[a];
		if(i<22)x^=(1<<i);
		ans[a]=max(ans[a],dep[a]+wolf[x]-dep[a]*2);
	}

	if(wolf[key[a]]<0)del.push_back(key[a]);
	wolf[key[a]]=max(wolf[key[a]],dep[a]);
	
	for(int i=0;i<g[a].size();i++)ans[a]=max(ans[a],ans[g[a][i].first]);
}
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a-1;i++){
		int p;
		scanf("%d%s",&p,in+i);
		p--;
		g[p].push_back(make_pair(i+1,in[i]));
	}
	dfs(0);
	for(int i=0;i<(1<<22);i++)wolf[i]=-mod;
	calc(0);
	
	for(int i=0;i<a;i++){
		if(i)printf(" ");
		printf("%d",ans[i]);
	}
	printf("\n");
}

Codeforces Round #385 (Div. 1)

Codeforces初めまして。

A B C D E Place
00:08 00:18 00:48 - - 14th

A:
算数と変な実装。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int p[1100];
int UF[1100];
int FIND(int a){
	if(UF[a]<0)return a;
	return UF[a]=FIND(UF[a]);
}
void UNION(int a,int b){
	a=FIND(a);b=FIND(b);if(a==b)return;
	UF[a]+=UF[b];UF[b]=a;
}
int has[1100];
int main(){
	int a,b,c;scanf("%d%d%d",&a,&b,&c);
	for(int i=0;i<c;i++){
		scanf("%d",p+i);
		p[i]--;
	}
	for(int i=0;i<a;i++)UF[i]=-1;
	for(int i=0;i<b;i++){
		int s,t;scanf("%d%d",&s,&t);s--;t--;
		UNION(s,t);
	}
	for(int i=0;i<c;i++)has[FIND(p[i])]=1;
	int ms=0;
	int ret=-b;
	for(int i=0;i<a;i++){
		if(UF[i]<0){
			int sz=-UF[i];
			ret+=sz*(sz-1)/2;
			if(has[i]){
				ms=max(ms,sz);
			}
		}
	}
	//printf("%d\n",ret);
	for(int i=0;i<a;i++){
		if(UF[i]<0&&has[i]==0){
			ret+=ms*(-UF[i]);
			ms+=-UF[i];
		}
	}
	printf("%d\n",ret);
}

B:
i-th bitが1のもの全部/0のもの全部のを計算しておけば全部に答えられる。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int ret[1100];

int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++){
		ret[i]=mod;
	}
	for(int i=0;i<10;i++){
		vector<int>v;
		for(int j=0;j<a;j++)if(j&(1<<i)){
			v.push_back(j);
		}
		if(v.size()){
			printf("%d\n",(int)v.size());
			for(int j=0;j<v.size();j++){
				if(j)printf(" ");
				printf("%d",v[j]+1);
			}
			printf("\n");fflush(stdout);
			for(int j=0;j<a;j++){
				int f;scanf("%d",&f);
				if(!(j&(1<<i)))ret[j]=min(ret[j],f);
			}
		}
		v.clear();
		for(int j=0;j<a;j++)if(!(j&(1<<i))){
			v.push_back(j);
		}
		if(v.size()){
			printf("%d\n",(int)v.size());
			for(int j=0;j<v.size();j++){
				if(j)printf(" ");
				printf("%d",v[j]+1);
			}
			printf("\n");fflush(stdout);
			for(int j=0;j<a;j++){
				int f;scanf("%d",&f);
				if((j&(1<<i)))ret[j]=min(ret[j],f);
			}
		}
	}
	printf("-1\n");
	for(int i=0;i<a;i++){
		if(i)printf(" ");
		printf("%d",ret[i]);
	}
	printf("\n");fflush(stdout);
}

C:
dp[i][j]=集合i、赤でj得したときの青の得の最大値
普通に典型なのにみんな遅いし自分も遅い。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int dp[1<<16][130];
char in[20];
int p[20];
int q[20];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++){
		scanf("%s%d%d",in+i,p+i,q+i);
	}
	for(int i=0;i<(1<<a);i++)for(int j=0;j<130;j++)dp[i][j]=-mod;
	dp[0][0]=0;
	int rn=0;
	for(int i=0;i<a;i++)if(in[i]=='R')rn++;
	for(int i=0;i<(1<<a);i++){
		int R=0;
		int B=0;
		for(int j=0;j<a;j++){
			if(i&(1<<j)){
				if(in[j]=='R')R++;
				else B++;
			}
		}
//		printf("%d: %d %d\n",i,R,B);
		for(int j=0;j<130;j++){
			if(dp[i][j]<0)continue;
			//printf("%d %d: %d\n",i,j,dp[i][j]);
			for(int k=0;k<a;k++){
				if(i&(1<<k))continue;
				dp[i+(1<<k)][j+min(R,p[k])]=max(dp[i+(1<<k)][j+min(R,p[k])],dp[i][j]+min(B,q[k]));
			}
		}
	}
	int rsum=0;
	int bsum=0;
	for(int i=0;i<a;i++){
		rsum+=p[i];
		bsum+=q[i];
	}
	int ret=mod*2;
	for(int i=0;i<130;i++)ret=min(ret,max(rsum-i,bsum-dp[(1<<a)-1][i]));
	printf("%d\n",ret+a);
}

D:
O(N^2 log N log ans)の解は有名だが間に合わなさげ。
反転を使うらしい。また今度。

レッドコーダーからtarget/LGMには3ヶ月でなれるか?

https://t.co/zV5iCKXjge
こんなものが最近話題になっている。

https://www.amazon.co.jp/dp/B01J9QIGF6/
あとこんなのも最近話題になっている。

そろそろ何もやってない気持ちでいっぱいになってきたし、競技プログラミングでこれを実証するのもいいんじゃないかと思ったので、試しにやってみようと思う。

続きを読む

Interview with Top-Level Competitive Programmers World-Wide

For Japanese readers: さすがにこれ全部和訳するのは大変すぎるのでこのままでゆるしてください。最近Google翻訳が大幅に改善しましたし。

This is the 20th article of Competitive Programming Advent Calendar 2016. I interviewed some coders from several countries. I asked about from how they practice problem solving to their daily life. Hope you enjoy it.

Introduction

Last month, the first world-wide programming contest in Japan*1, named "CODE FESTIVAL 2016". Also, I'm interested in how different competitive programmers in country A is from those in country B (where A != B). Besides, I can easily guess that it also depends on their age. So I gathered several top-level competitive programmers to ask these questions and write this article for sharing information among programmers worldwide.

However, this does not show the entire "competitive programming" world. You can know more about it by making friends and talking about programming contest life. I also would like to encourage programmers communicating with each other, no matter where they are from.

Interview Participants

tozangezan 🐺 (Japan)
Who planned this interview and wrote this blog. I like wolves.

polequoll 🍇 (South Korea)
I didn't know much about him until CODE FESTIVAL, but it turned out that I and he had won the same prize (3rd-8th awards) in the 2nd Samsung Collegiate Programming Contest.

dnk 🐝 (Viet Nam)
He's currently studying at Tokyo Institute of Technology in Japan, so I've met him several times before, (especially during the World Finals 2016; he was a team member from VNU University of Engineering in Viet Nam).

KAN 🐱 (Russia)
Perhaps very few coders don't know about him; He won 3rd place in IOI 2013, and still has very high Codeforces rating.

yutaka1999 (Japan)
He's still a high school student, even though he's already won three Gold Medals in IOI. I hope for him winning IOI on 2017, that is the last chance of IOI.

General Questions

Self introduction (user name, school, country, contest result, favorite problem genres, etc...)

tozangezan: I'm tozangezan from Japan, studying at the University of Tokyo. One of the most biggest achievement in programming contest is Silver medal in ICPC World Finals 2014. I like combinatorics problem, as well as implementation!

polequoll: Hello, I'm polequoll from Seoul National University in Korea. My favorite problem genre is data structures, as well as some tree problems. However, I'm not good at constructive algorithms and some optimal game problems.

dnk: I'm dnk from Vietnam, studying at Tokyo Institute of Technology. Maybe my biggest achievement is ACM ICPC Hanoi Regional 2015 champion with my team (from VNU University of Engineering). I like combinatoric and dynamic programming

KAN: Hi, I'm KAN from Russia, I study at the Nizhny Novgorod State University. I think the biggest achievements are two gold medals at IOI (2013 and 2014), and bronze medal at ACM ICPC Finals 2016

yutaka1999: I'm yutaka1999 from Japan. I'm a high school student and I like participating in contests like IOI.

When, and why did you start competitive programming?

tozangezan: As far as I know, my first contest experience was the preliminary round of national OI in 2008 (when I didn't even know how to read integers). I was in math club of my junior high school then, and I and my friends (including semiexp) started thanks to the elder student, who's a former IOI gold medalist.

polqeuoll: I started competitive programming quite early (from 13 years old), but actually the time I intensively focus on competitive programming was after high school graduation. For me, ACM-ICPC was the biggest momentum.
tozangezan: So early!

dnk: I officially started competitive programming when I was a high school first year student because I thought I can do programming and getting a good place in national OI could help me enter a university without taking entrance examination.

KAN: I started programming when I was about 10 because my older brother participated in programming competitions as well.

What was your first goal of programming contest?

tozangezan: My first goal was to go to final round of domestic OI contest, and being selected as national team for IOI was my big dream when I was in high school.

polequoll: In my case, my first goal was to be awarded in National ACM-ICPC regional (and to get an WF ticket) with my friends.

dnk: I don't remember my first goal clearly but I think it was something like to get high rating in Codeforces (probably to division 1). The big dream was to get a slot in the IOI team but I could not achieve that dream.

KAN: Well, I don't know what was my first goal, probably to win some local contest
tozangezan: Always our dream ;)

How did you choose your handle name for contest websites?

tozangezan: "tozan" means "climing mountain" and "gezan" means "going down mountain", but we don't have the term for "climing then going down mountain". "tozangezan" is my answer for the question. But I don't know why I use for contests. I didn't climb mountains at that time, nor did I know hill-climbing algorithm. (Now I usually go to mountains because I'm ecology major).

polequoll: I like alphabet P and Q, and I want to make my unique handle name (I want Google don't have a search result of my (new) handle name before I create it.). That's why I choose 'polequoll' as my handle name.

dnk: At first, my handle was not dnk. When Codeforces allowed users to change handle in New Year, I changed my first handle to my second handle which is my full name + birth year. In the second time I changed it to dnk (first letters of my full name) to make it shorter (from 15 -> 3 characters).

KAN: There was a tradition in Nizhny Novgorod to make handles with the first two letters of surname and the first letter of given name. That's why I'm KAN. And I chose KalininN as my second handle because it wasn't possible to register "KAN" at topcoder
tozangezan: Is that a common way to make handle name in Russia?
KAN: No, only in Nizhny Novgorod

About Competitions

Where do you usually practice?

tozangezan: It varies a lot. Sometimes I use Japanese contest website such as Aizu Online Judge or AtCoder, but I like TopCoder's mathematical problems so sometimes I concentrate on TopCoder. I don't like to practice on Codeforces though ;(

polequoll: I mainly practice with past Codeforces problems (I had practiced with the problems (excepting Div2AB and Div1E) from #201 to #382) as well as Baekjoon Online Judge (which is most famous online judge in Korea).

dnk: At first I was doing very simple problems in UVA Online Judge. After that I did problems in the Vietnam site of Sphere Online Judge. I did participated in Codeforces and TopCoder contests too but not so often, possibly due to the fact that those contests were often very late in my local time. I also solved problems that older students or my teachers gave me (I don't know the source of many problems)
tozangezan: I feel the same about contest time ...

KAN: I don't like upsolving so when I used to practice a lot, I simply wrote as many contests as I could: codeforces, topcoder, some more specific contests like USACO or COCI. Also, there are several on-site camps in Russia for studying competitive programming.

Do you study algorithms from books? If so, which book helped you the most?

tozangezan: here's a popular textbook for competitive programming in Japan, named Programming Contest Challenge Book, which is written by iwiwi, wata, and kita_masa. It's called "Ant Book" in Japan (because an ant is drawn on the top) It has some advanced techniques and red coders can learn some from it.

polequoll: I study algorithms from contest editorials and posts rather than books.
tozangezan: oh you don't have the book popular in Korea? I've heard some of it
polqeuoll: There is a textbook called Jongman Book which is most popular in Korea, but actually I don't have that book. :$

dnk: I did read a famous Vietnamese (e-)book written by Le Minh Hoang for understanding the logics of algorithms but for coding, most of the times I searched for codes from the internet. We called it DSAP (Data Structure + Algorithm = Program).
tozangezan: Sounds like PPAP
dnk: PPAP is relatively new

KAN: I didn't study books a lot, instead, I tried a lot to ask more experienced coders about some techniques or algorithms (or read some articles about them). However, probably the most popular book in Russia is Introduction to Algorithms, many people find it really helpful.

yutaka1999: At first I study from the Japanese book Programming Contest Challenge Book , but nowdays I don't read it.

When you started programming contest, how was the practicing environment different from now?

tozangezan: At that time, there're few online judges, and Codeforces was not born yet. I practiced on POJ (Peking University Online Judge) but the environment was so terrible. They don't use -O2 option for C++ source. Actually I used Windows Me for the first participation

polequoll: It's almost same except for the version of Visual Studio. (6.0 -> 2012)

dnk: Basically the same

Which language do you use for contests?

tozangezan: C++. definitely.

polequoll: I use only C++ for competitive programming.

dnk: C++

KAN: Regarding programming language, now I use C++ and a bit Python

yutaka1999: C++

Which editor do you use for contests?

tozangezan: Recently I use Mac for contests and I use Sublime Text on that. Notepad++ if Windows.

polequoll: Visual Studio only. Recently, I tried to use Code::Blocks due to the ACM-ICPC environment, but I threw away it from my computer after the contest, because it's so so buggy. :$
tozangezan: I wonder if many Korean coders use Visual Studio because I could use only VC++ compiler at SCPC. *2
polequoll: Yes, Korean coders usually use Visual Studio. I think it is due to the past KOI environment.

dnk: vim, at the beginning of some onsite contest like ACM, maybe I will use other editor because I might not have enough time to config vim.
dnk: by the way, in Vietnam, ACM ICPC is called ACM instead of ICPC even though it seems to be incorrect

KAN: I use Kate as a part of Kubuntu, however, editor doesn't really matter if it has console and/or compiler integrated.

yutaka1999: I usually use Sakura Editor , which is a Japanese editor.

Which regular (weekly-monthly) contest is your favorite?

tozangezan: I hate weekly contests

polequoll: I like Codeforces, but actually I rarely parcitipate it due to the timezone.

dnk: Actually, I am not taking part in regular contests for years

yutaka1999: I like Topcoder because problems are interesting to me.

Is there any other favorite contest? (annual, irregular, etc...)

tozangezan: I wish I could take part in World Finals once more...! Besides I like GCJ

polequoll: I like COCI and Latin America Regionals problems.

dnk: Onsite contests in Japan are good (tenkaichi, codefes, etc)

KAN: I like codeforces and topcoder (however, the fact that the Topcoder Arena is not working sometimes is really annoying). Also, I forgot to mention codefights, I find it really good and fun both for beginners and experienced coders. I really enjoy many things they have (head2head, marathons and arcade), however, I don't have much time to compete there

yutaka1999: I like USACO, JOI and IOI. This is Bessie. [There was a cow emoticon here]

Community

Do you have friends to discuss after contests? How do you contact with those friends? (which social media?)

tozangezan: Japanese coders discuss problems after (almost every) contest on Twitter. Sometimes we use Slack but it's less popular.

polequoll: Yes, I mainly discuss the problems with my ACM-ICPC team members. In Korea, we use a messenger called 'KakaoTalk'.

dnk: I occasionally discuss with my friends after contests (face-to-face meeting or Facebook Messenger)

KAN: On onsite events, we usually discuss problems face-to-face after a contest. It is also a place where you can learn a new technique or algorithm to solve some of the contest's problems, everyone is happy to explain his solution to someone and to chat about some difficulties. Regarding online contests, it's more difficult but sometimes I discuss problems via messengers, and sometimes we talk about recent contest when I meet with someone face-to-face.

How often, and when do you meet with competitive programming friends face to face?

tozangezan: Recently there're many onsite contests in Japan, but other than that I don't do a lot. But I've been to training camp hosted by rng_58 twice (it's not like training camp like Petrozavodsk. It's much smaller).

polequoll: Almost everyday during the semester. During the vacation, I had regularly met my ACM-ICPC team members to practice the contest.

dnk: When I was in high school, every day, we were training together for national OI.

KAN: Regarding meeting with friends: not so often. When I was in high school, nobody in my school was competing on a regular basis, so I met with competitive programming friends at some camps or big contests.
polequoll: Oh, us too

yutaka1999: I meet my programming friends only in onsite events. When I meet them in school, we don't talk a lot about programming.
tozangezan: It's surprising. When I met contest friends in high school I talked almost only about contests. (I and yutaka1999 are from the same high school)
yutaka1999: I talk about some school events such as school festivals, athletic meetings and tests, but actually, I don't have so many chances to talk with them (because they are not classmates.)

Do you have any other hobbies to share with those friends except contests?

tozangezan: I and some others like to play rhythm games (such as beatmania IIDX or Dance Dance Revolution), and solving pencil puzzles...?

polequoll: Many games - rhythm games, Hearthstone, Overwatch, ...

dnk: I think we will start from competitive programming and by some mysterious ways, the conversation will be smoothly moved to another topic

KAN: There are a lot of coders in Russia who enjoy some sport games. I like volleyball and frisbee, and there are some groups playing them almost in every long break at onsite competitions. Also, there are people who like soccer. Another hobby many coders enjoy are board games.

Is there any interesting term, fact or meme in the community?

tozangezan: Too many. Japanese coders are playing with words all day long, such as finding haiku-style sentence from daily tweet or speech or problem statements.

polequoll: There is unique atmosphere..? when competitive programmers talk, but I couldn't give them in a sentences because it's very subtle :$ . Actually, I want to ask the meaning of the word 'Retsu-mo', which makes laugh in Codefestival. *3
tozangezan: Retsu-mo means submodular function
polequoll: I've never heard of submodular function, maybe I have to study it

dnk: Maybe some terms: buffalo = strong implementation skill (maybe 高い実装力 in Japanese), turtle = passing a test set or get a high rank by luck.
tozangezan: I'll use buffalo from now

KAN: Well there are many specific terms in the language we use, but they're just some shortened (and easier to pronounce) forms of mathematical terms I think.

yutaka1999: I think the way I talk with competitive programmers is different from that I talk with my other friends.

Do you have contest friends outside your home-country?

tozangezan: I sometimes go to onsite contest overseas and meet some of them. Especially I often talk with Korean coders because I can speak Korean a little, then one Korean coder (maybe dnk also knows him) introduced me about upcoming contest in Korea, and its prize was so good ;) Anyway, I like to talk with contestants from over the world.

polequoll: Actually, I have almost no friends outside my country

dnk: Yes, I have Japanese friends who are competitive programmers

KAN: Technically, I have some foreign friends, however, they are all from neighboring countries and speak Russian. (and there is no difference between them and Russian friends)

yutaka1999: I have many friends on Facebook.
tozangezan: optimal answer for this question

Outside "Competitive" Programming

Do you write programs other than for contests?

tozangezan: No

polequoll: Yes, I agree with sometimes it's more interesting.

dnk: Almost no

KAN: Yes, I do and sometimes it's more interesting

yutaka1999: No.

Are you planning to work as software engineer after graduation?

tozangezan: If I can research my area (ecology) for all my life, I won't. But some software engineering teams also sound interesting. At least I have plenty of time to decide.
dnk: why are you studying ecology?
tozangezan: Of course because I like the subject.
KAN: I think you'll need to write some programs to study the results of some research and so on
tozangezan: definitely yes. My lab is about theoretical ecology, so simulation of ecosystem is one of the most popular topic.

polequoll: I'm not sure. Currently, I'm interested in a research (such as graduate school) rather than working.

dnk: Yes.

KAN: I study physics, and I find programming as one of the most demanded skills a scientist should have

yutaka1999: I'm not sure. I'm interested in mathematics.

How do you feel about contests-holding companies?

tozangezan: http://m.memegen.com/8wq2ys.jpg
tozangezan: To be serious, it's so helpful that I can choose from them if I want to work as internship.

polequoll: I like them. Sometimes, I wonder how they can make earnings.

dnk: In general, I like those companies.

KAN: How can anyone dislike them?

yutaka1999: I like onsite contests, so I like those companies.

What do you do for programming contest community, besides competing in contests? (ex. problem writing, tutoring, write learning materials, creating tools, etc)

tozangezan: I sometimes write problems for TopCoder and AtCoder, I'm one of the tutors of JOI (Japanese OI), and create Youtube videos about contest techniques. (but for the last one, I started it just for practicing English)

polequoll: Currently, almost nothing. I want to write several problems someday...

dnk: Back in Vietnam, I was translating some Japanese problem statements

KAN: I write and help to prepare some problems for local contests of different level and sometimes for codeforces. I review codeforces' rounds. I train high-school students from my city for team and individual contests
tozangezan: "I train high-school students from my city" sounds interesting
KAN: We have a system called "circles" in Russian in which high-school students can attend some additional courses after school. They exist in many schools in almost every city, some of them are city-wide and some of them are just for one school. High-school students gather to study something together with the help of some tutors.
tozangezan: It's like our system, even though we don't have tutors.

yutaka1999: I like problem writing, but it's just for the fun of it and not for contests... (Note that some of yutaka1999's problems are available at Code Festival 2016's tournament. )

Where is your favorite place you have visited for onsite contests?

tozangezan: Ekaterinburg (Russia, WF2014) is my favorite. There was an event called ICPC Quest in recent World Finals, and I was playing so hard. Thanks to the quests and relatively long contest schedule, I can visit so many places in the city. I remember that I and my teammate and coach walked for an hour to get to the KHL (hockey league in Russia) team's stadium to take photos.

polequoll: SCPC(Samsung Programming Contest) and CODE FESTIVAL

dnk: Maybe Japan. I visited Thailand for ACM ICPC WF and Regionals but at the time of my visit the weather was too hot and air conditionals were too cold.

KAN: Regarding the favorite place, I think for me it is Australia (IOI 2013)

yutaka1999: Maybe it's Taiwan, where IOI 2014 was held.

Conclusion

Why do you continue participating in contests?

tozangezan: Of course one of the reason is it's fun, but it's more complicated. Most of my friends are competitive programmers and I earn money from contests (as participant, writer, tester, etc). I can't imagine life without contest.

polequoll: Obviously, it's fun to solve tricky problems, and I like discussing ideas with my friends.

dnk: I almost earn no money from programming contest but I continue participating because it's fun (in some sense). If I did not meet Japanese coders in ACM ICPC WF maybe right now I'm not participating in programming contests.

KAN: Actually, I don't compete regularly now, I only take part in some annual interesting competitions for fun

This is the last question. What is your current goal?

tozangezan: I had three goals, "becoming member of IOI national team", "win medal at World Finals" and "go to top-25 onsite final of international contests (such as GCJ and FHC)". I've achieved all of them. What else can I set for my goals...? I don't know. Maybe "cause good effect on increasing the number of competitive programmers"...?

polequoll: Actually, I don't have a clear goal currently (in terms of a contest achievement). In other words, I simply want to enjoy competitive as long as I lives

dnk: About competitive programming, I had a goal "to get a slot in IOI team" but I failed. After that, most of my goals are more about foreign language skills (for example: remembering the Vietnamese reading of 2000 kanjis in 3 months)
tozangezan: I hope for "Japanese remembering 2000 GRE words in 3 months"
dnk: Those are two completely different stories as English has little connection with Japanese.

KAN: I don't know actually. I think now my goal is to have as much fun as I can competing and preparing contests. Another my goal is to teach others.

yutaka1999: I want to become smart and one of my definite goals is to get a higher rank in IOI.

Conclusion

Perhaps this is the first time to hold such project. Unfortunately, there were only 5 participants of this interview, and their home-country and their age is too limited. I gathered interview participants in Code Festival (except yutaka1999; the contest was only available for university students, and he is a high school student now) and I'm hoping we can do similar things at next year's Code Festival (if available).

Thanks interview participants for attending. Thanks those whom I asked for during the contest day for spending time. Thank you for reading this article.

Comment here or on Codeforces if you would like.

🐺🍇🐝🐱☺️

*1:Of course that's not true. We'd hold GCJ Finals once and ACM-ICPC World Finals once. However, there were no international contests sponsored by Japanese companies.

*2:The 2nd Samsung Collegiate Programming Contest, held in Seoul. On this August, I and polequoll took part in the contest. My blog entry of the contest is here. You can translate by using Google Translate that is improved recently.

*3:In the Code Festival contest, a professional calligrapher came to perform in front of participants during the ending ceremony, and one prize (best calligraphy award) was that the participant could request words to draw. He asked 'Retsu-mo(劣モ)', submodular function in Japanese. The calligrapher, international participants, and even most Japanese contestants didn't know what it meant.

JMC2016-2017 問題4

余談: タイトルバーには JMC2015-2016 と書かれています。

明日はJOIの予選だそうで、今日はその模擬予選というのをやっていたようです。皆さん満足いく準備はできましたか?明日の予選では実力を発揮できそうですか?

IOI2012に参加した僕からの一言アドバイスです。

「15:23以前に問題4に何の疑いもなく解答を提出して満点を取った人は反省してください。」

以下、詳細を説明していきます。

問題の概要

二次元フィールドの一部が赤く、残りが白く塗られているので日本国旗を作りたい。塗り替える個数の最小値を求めよ。

以下のようなものが日本国旗に当てはまります。

  • 日本国旗のように真ん中が丸いもの
  • 真っ白
  • イングランドの国旗の周りを白く囲ったもの(!)

想定している定義は、IOI2012のCityの55点解法と同じく、赤いマスが行、列ごとに一つの連結成分になっていることのようです。

当初の問題文にあった定義

連結性がおかしくて正しくない例の図Dまで条件を満たすことになっていました。これは日本語のミスなので気にしないことにします。

Challenge Phase 第1問

  • 国旗に垂直な直線と水平な直線について線対称となっている.
  • 任意の赤のマスから, 他の赤のマスへ, 辺を共有している赤のマスを辿ってたどり着くことが出来る.また, 赤のマスによって囲まれる白のマスは存在しない.
  • 1 ≦ i ≦ H / 2 - 1 を満たす整数 i について, 国旗の i 行目に含まれている赤のマスの個数は, 国旗の i + 1 行目に含まれている赤のマスの個数以下である.
  • 国旗の 1 行目, 1 列目, H 行目, および W 列目に赤のマスが含まれない.

さっき書いた意図に反するケースを見つけてください。見つかりましたか?

答えです。白い文字で書きました。


8 8
WWWWWWWW
WRWWWWRW
WRRWWRRW
WWRRRRWW
WWRRRRWW
WRRWWRRW
WRWWWWRW
WWWWWWWW

要は、アラバマの州旗を白く囲んだものまで条件を満たしてしまうことになりました。これだけなら容易に変なケースは作り放題です。

ということで以下のような修正が加わりました。

Challenge Phase 第2問

  • 国旗に垂直な直線と水平な直線について線対称となっている.
  • 任意の赤のマスから, 他の赤のマスへ, 辺を共有している赤のマスを辿ってたどり着くことが出来る.また, 赤のマスによって囲まれる白のマスは存在しない.
  • 1 ≦ i ≦ H / 2 - 1 を満たす整数 i について, 国旗の i 行目に含まれている赤のマスの個数は, 国旗の i + 1 行目に含まれている赤のマスの個数以下である.
  • 1 ≦ i ≦ W / 2 - 1 を満たす整数 i について, 国旗の i 列目に含まれている赤のマスの個数は, 国旗の i + 1 列目に含まれている赤のマスの個数以下である.
  • 国旗の 1 行目, 1 列目, H 行目, および W 列目に赤のマスが含まれない.

一見、これで正しそうに見えます。それでは運営の意図に反するケースを作ってください。こっちは少し難しいです。

答えです。やっぱり白く書いておきました。


16 14
WWWWWWWWWWWWWW
WWWWRRWWRRWWWW
WWWWRRWWRRWWWW
WWWWRRRRRRWWWW
WRRWWWRRWWWRRW
WWRRWWRRWWRRWW
WWRRWWRRWWRRWW
WWWRRRRRRRRWWW
WWWRRRRRRRRWWW
WWRRWWRRWWRRWW
WWRRWWRRWWRRWW
WRRWWWRRWWWRRW
WWWWRRRRRRWWWW
WWWWRRWWRRWWWW
WWWWRRWWRRWWWW
WWWWWWWWWWWWWW

最終的に

下のような条件になりました。これなら正しいと思います。

  • 国旗に垂直な直線と水平な直線について線対称となっている.
  • 任意の赤のマスから, 他の赤のマスへ, 辺を共有している赤のマスを辿ってたどり着くことが出来る.また, 赤のマスによって囲まれる白のマスは存在しない.
  • 1 ≦ i ≦ H / 2 - 1 を満たす整数 i について, 国旗の i 行目に含まれている赤のマスの個数は, 国旗の i + 1 行目に含まれている赤のマスの個数以下である.
  • 各行について, 赤マスは一つのまとまりとなって配置されている. すなわち, ある行に赤マスがあるのであれば, その行の赤マスがある左端の列を L 列目, 右端の列を R 列目として, L ≦ i ≦ R を満たすすべての i について, i 列目は赤マスとなっている.
  • 国旗の 1 行目, 1 列目, H 行目, および W 列目に赤のマスが含まれない.

まとめ

定義が難しそうな問題はちゃんと定義から変なものが構成できないかどうか証明して確認しよう!