tozangezan's diary

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

ひとり地区予選 2018-2019 ACM-ICPC Southeast USA Regional

これはつまらん(確信)。3時間強の練習会。

B: Count the Bits
5万回見た。ところで間違えてAに提出してWA出した

long long dp[140][140][1100];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	dp[0][0][0]=1;
	for(int i=0;i<b;i++){
		for(int j=0;j<=i;j++){
			for(int k=0;k<a;k++){
				if(dp[i][j][k]==0)continue;
				dp[i+1][j][k*2%a]=(dp[i+1][j][k*2%a]+dp[i][j][k])%mod;
				dp[i+1][j+1][(k*2+1)%a]=(dp[i+1][j+1][(k*2+1)%a]+dp[i][j][k])%mod;
			}
		}
	}
	long long ret=0;
	for(int i=0;i<=b;i++){
		ret=(ret+i*dp[b][i][0])%mod;
	}
	printf("%lld\n",ret);
}

C: Exam
無。

char in[2][1100];
int main(){
	int a;scanf("%d",&a);
	scanf("%s%s",in[0],in[1]);
	int n=strlen(in[0]);
	int ret=0;
	for(int i=0;i<n;i++){
		if(in[0][i]==in[1][i]&&a){
			a--;ret++;
		}
	}
		int cn=0;
		for(int i=0;i<n;i++){
			if(in[0][i]!=in[1][i])cn++;
		}
		ret+=cn-a;
	printf("%d\n",ret);
}

F: Knockout
簡単な問題が全く見つからないからうだうだしてたら他の人が解いたので自分もやった

char in[110];
int r[110];
double dp[2][1<<10];
double calc(int a,int b){
	if(dp[a][b]>=-0.5)return dp[a][b];
	double ret=0;
	for(int i=2;i<=12;i++){
		double p=1.0/36;
		p*=min(12-i,i-2)+1;
		double tmp=-1;
		bool ok=false;
		int val=0;
		for(int j=0;j<10;j++){
			if(b&(1<<j)){
				val*=10;val+=j;
			}
		}
		if(a==0)tmp=val;
		for(int j=0;j<(1<<10);j++){
			if((b&j)!=j)continue;
			int cur=0;
			for(int k=0;k<10;k++)if(j&(1<<k))cur+=k;
			if(cur!=i)continue;
			ok=true;
			double tt=calc(a,b-j);
			if(a==0&&tt<tmp){
				tmp=tt;
			}
			if(a==1&&tt>tmp){
				tmp=tt;
			}
		}
		if(a==1&&ok==false){
			tmp=val;
		}
		ret+=p*tmp;
	}
//	printf("%d %d: %f\n",a,b,ret);
	return dp[a][b]=ret;
}
int main(){
	scanf("%s",in);
	int a,b;scanf("%d%d",&a,&b);
	int n=a+b;
	int st=0;
	int v=0;
	for(int i=0;in[i];i++){
		r[in[i]-'0']=1;
		v*=10;
		v+=in[i]-'0';
		st+=(1<<(in[i]-'0'));
	}
	for(int i=0;i<2;i++)for(int j=0;j<(1<<10);j++)dp[i][j]=-1;
	
	int mv1=0;
	double b1=v;
	int mv2=0;
	double b2=-1;
	for(int i=0;i<(1<<10);i++){
		if((i&st)!=i)continue;
		int St=0;
		for(int j=0;j<10;j++){
			if(i&(1<<j))St+=j;
		}
		if(St!=n)continue;
	//	printf("%d %d\n",st,i);
		double tmp1=calc(0,st-i);
		double tmp2=calc(1,st-i);
		if(tmp1<b1){
			b1=tmp1;mv1=i;
		}
		if(tmp2>b2){
			b2=tmp2;mv2=i;
		}
		
	}
	if(mv1==0){
		printf("-1");
	}else{
		for(int i=0;i<10;i++)if(mv1&(1<<i))printf("%d",i);
	}
	printf(" %.5f\n",b1);
	if(mv2==0){
		printf("-1");
		b2=v;
	}else{
		for(int i=0;i<10;i++)if(mv2&(1<<i))printf("%d",i);
	}
	printf(" %.5f\n",b2);
	
}

J: Area Rug
5万回見た。

char in[1100][1100];
int sum[1100][1100];
int ans[11000];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++)scanf("%s",in[i]);
	for(int i=0;i<a;i++)for(int j=0;j<a;j++){
		if(in[i][j]=='D')sum[i+1][j+1]++;
	}
	for(int i=0;i<=a;i++)for(int j=0;j<=a;j++){
		sum[i+1][j]+=sum[i][j];
	}
	for(int i=0;i<=a;i++)for(int j=0;j<=a;j++){
		sum[i][j+1]+=sum[i][j];
	}
	for(int i=0;i<=a-b;i++){
		for(int j=0;j<=a-b;j++){
			ans[sum[i+b][j+b]-sum[i+b][j]-sum[i][j+b]+sum[i][j]]++;
		}
	}
	for(int i=0;i<=b*b;i++){
		if(ans[i]){
			printf("%d %d\n",i,ans[i]);
		}
	}
}

I: Rectangles
Fortune Telling。

int segtree[524288];
int laz[524288];
int z[210000];
pair<pair<int,int>,pair<int,int> > ev[210000];
void update(int a,int b,int c,int d,int e){
	if(laz[e]){
		laz[e]=0;
		segtree[e]=(z[b+1]-z[a])-segtree[e];
		if(a!=b){
			laz[e*2]=!laz[e*2];
			laz[e*2+1]=!laz[e*2+1];
		}
	}
	if(d<a||b<c)return;
	if(c<=a&&b<=d){
		laz[e]=!laz[e];
	}else{
		update(a,(a+b)/2,c,d,e*2);
		update((a+b)/2+1,b,c,d,e*2+1);
		segtree[e]=segtree[e*2]+segtree[e*2+1];
	}
	if(laz[e]){
		laz[e]=0;
		segtree[e]=(z[b+1]-z[a])-segtree[e];
		if(a!=b){
			laz[e*2]=!laz[e*2];
			laz[e*2+1]=!laz[e*2+1];
		}
	}
}
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++){
		int X1,Y1,X2,Y2;
		scanf("%d%d%d%d",&X1,&Y1,&X2,&Y2);
		ev[i*2]=make_pair(make_pair(X1,0),make_pair(Y1,Y2));
		ev[i*2+1]=make_pair(make_pair(X2,1),make_pair(Y1,Y2));
		z[i*2]=Y1;
		z[i*2+1]=Y2;
	}
	std::sort(z,z+a*2);
	std::sort(ev,ev+a*2);
	z[a*2]=mod;
	long long ret=0;
	for(int i=0;i<a*2;i++){
		int at=ev[i].first.first;
		int ty=ev[i].first.second;
		int YL=ev[i].second.first;
		int YR=ev[i].second.second;
		int Y1=lower_bound(z,z+a*2,YL)-z;
		int Y2=lower_bound(z,z+a*2,YR)-z;
		if(i){
			long long ks=ev[i].first.first-ev[i-1].first.first;
			ret+=ks*segtree[1];
		}
		update(0,262143,Y1,Y2-1,1);
	}
	printf("%lld\n",ret);
}

K: To Tell the Truth
問題文の意味を推測する。

int L[1100];
int R[1100];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++)scanf("%d%d",L+i,R+i);
	int ret=-1;
	for(int i=0;i<=a;i++){
		int cur=0;
		for(int j=0;j<a;j++){
			if(L[j]<=i&&i<=R[j])cur++;
		}
		if(cur==i)ret=i;
	}
	printf("%d\n",ret);
}

D: Illiteracy
クソゲー(問題文が読みにくくて条件を見落としまくる)。

int bfs[2000000];
char in[2][10];
int t[10];
int v[10];
int main(){
	scanf("%s%s",in[0],in[1]);
	for(int i=0;i<2000000;i++)bfs[i]=-1;
	int now=0;
	for(int i=0;i<8;i++){
		now*=6;
		now+=in[0][i]-'A';
	}
	int goal=0;
	for(int i=0;i<8;i++){
		goal*=6;
		goal+=in[1][i]-'A';
	}
	queue<int>Q;
	Q.push(now);
	bfs[now]=0;
	while(Q.size()){
		int at=Q.front();
		Q.pop();
		int tmp=at;
		for(int i=7;i>=0;i--){
			t[i]=tmp%6;tmp/=6;
		}

		for(int i=0;i<8;i++){
			if(t[i]==0){
				for(int j=0;j<8;j++)v[j]=t[j];
				if(i)v[i-1]=(v[i-1]+1)%6;
				if(i<7)v[i+1]=(v[i+1]+1)%6;
			}else if(t[i]==1){
				for(int j=0;j<8;j++)v[j]=t[j];
				if(i&&i<7)v[i+1]=v[i-1];
			}else if(t[i]==2){
				for(int j=0;j<8;j++)v[j]=t[j];
				v[7-i]=(v[7-i]+1)%6;
			}else if(t[i]==3){
				for(int j=0;j<8;j++)v[j]=t[j];
				if(i<4){
					for(int j=0;j<i;j++)v[j]=(v[j]+1)%6;
				}else{
					for(int j=i+1;j<8;j++)v[j]=(v[j]+1)%6;
				}
			}else if(t[i]==4){
				for(int j=0;j<8;j++)v[j]=t[j];
				if(i&&i<4){
					v[0]=(v[0]+1)%6;
					v[i*2]=(v[i*2]+1)%6;
				}else if(i>=4&&i<7){
					v[7]=(v[7]+1)%6;
					v[i-(7-i)]=(v[i-(7-i)]+1)%6;
				}
			}else{
				for(int j=0;j<8;j++)v[j]=t[j];
				if(i%2==0){
					v[i/2+4]=(v[i/2+4]+1)%6;
				}else{
					v[i/2]=(v[i/2]+1)%6;
				}
			}
			int to=0;
			for(int j=0;j<8;j++){
				to*=6;
				to+=v[j];
			}
			if(bfs[to]==-1){
				bfs[to]=bfs[at]+1;
				Q.push(to);
			}
		}
	}
	printf("%d\n",bfs[goal]);
}

E: Inversions
(どこかで見たことがあるような気もする)。計算量からしてどうせ凸なので頑張って凸性DPを書く。様々なものをO(1)で求めるために前計算しないといけなくて苦痛。

long long dp[110][210000];
int p[210000];
vector<int>v;
int bit[120];
int sum(int a,int b){
	if(a)return sum(0,b)-sum(0,a-1);
	int ret=0;
	for(;b>=0;b=(b&(b+1))-1)ret+=bit[b];
	return ret;
}
void add(int a,int b){
	for(;a<120;a|=a+1)bit[a]+=b;
}
int cnt[110][210000];
long long stf[110][210000];
int cnt2[110][210000];
long long stf2[110][210000];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++)scanf("%d",p+i);
	for(int i=0;i<a;i++){
		if(p[i])v.push_back(p[i]);
	}
	long long ret=0;
	for(int i=0;i<v.size();i++){
		ret+=sum(v[i]+1,110);
		add(v[i],1);
	}
	for(int i=0;i<a;i++){
		if(p[i]){
			cnt[p[i]-1][i]++;
		}
	}
	for(int i=b;i>0;i--)for(int j=0;j<=a;j++){
		cnt[i-1][j]+=cnt[i][j];
	}
	for(int i=0;i<=b;i++)for(int j=0;j<=a;j++){
		cnt[i][j+1]+=cnt[i][j];
	}
	for(int i=0;i<a;i++){
		if(p[i]==0){
			stf[0][i+1]++;
			for(int j=1;j<=b;j++){
				stf[j][i+1]=cnt[j][i];
			}
		}
	}
	for(int i=0;i<=b;i++){
		for(int j=0;j<=a;j++){
			stf[i][j+1]+=stf[i][j];
		}
	}

//	for(int i=0;i<=b;i++){
//		for(int j=0;j<=a;j++)printf("%lld ",stf[i][j]);printf("\n");
//	}
	for(int i=0;i<a;i++){
		if(p[i]){
			cnt2[p[i]+1][i]++;
		}
	}
	for(int i=0;i<=b;i++)for(int j=0;j<=a;j++){
		cnt2[i+1][j]+=cnt2[i][j];
	}
	for(int i=0;i<=b;i++)for(int j=a;j>0;j--){
		cnt2[i][j-1]+=cnt2[i][j];
	}
	for(int i=0;i<a;i++){
		if(p[i]==0){
			stf2[0][i+1]++;
			for(int j=1;j<=b;j++){
				stf2[j][i+1]=cnt2[j][i];
			}
		}
	}
	for(int i=0;i<=b;i++){
		for(int j=0;j<=a;j++){
			stf2[i][j+1]+=stf2[i][j];
		}
	}

	for(int i=0;i<=b+1;i++)for(int j=0;j<=a;j++)dp[i][j]=-inf;
	dp[b+1][0]=0;
	vector<int>ind;
	ind.push_back(0);
	for(int i=0;i<a;i++)if(p[i]==0)ind.push_back(i+1);
	for(int i=b;i>=1;i--){
		int at=0;
		for(int j=0;j<=ind.size();j++)dp[i][j]=dp[i+1][j];
		for(int j=0;j<ind.size();j++){
			long long prev=-1;
			long long kk=0;

			while(at<=j){
				kk=dp[i+1][at];
				long long tmp=kk+(long long)(stf[0][ind[j]]-stf[0][ind[at]])*stf[0][ind[at]]+(stf[i][ind[j]]-stf[i][ind[at]])+(stf2[i][ind[j]]-stf2[i][ind[at]]);
				if(prev>tmp){
					break;
				}
				dp[i][j]=max(dp[i][j],tmp);prev=tmp;at++;
			}
			at--;
		//	printf("%d %d: %d %lld\n",i,j,at,dp[i][j]);
		}
	}
	long long mm=0;
	for(int i=1;i<=b+1;i++)for(int j=0;j<=a;j++)mm=max(mm,dp[i][j]);
	printf("%lld\n",ret+mm);
}

公式のGの答えが間違っていたらしい。

ひとり地区予選 2016-2017 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)

3時間。クッキーチームには勝てなかったけど、一人でこれだけできれば上出来。

A: Alphabet
リス。

char in[52];
int dp[60];
int main(){
	scanf("%s",in);
	int n=strlen(in);
	for(int i=0;i<n;i++){
		dp[i]=max(dp[i],1);
		for(int j=0;j<i;j++){
			if(in[j]<in[i])dp[i]=max(dp[i],dp[j]+1);
		}
	}
	int ret=0;
	for(int i=0;i<n;i++)ret=max(ret,dp[i]);
	printf("%d\n",26-ret);
}

C: Cameras
狼はGreedyをBITでごまかす。

int bit[110000];
int sum(int a,int b){
	if(a)return sum(0,b)-sum(0,a-1);
	int ret=0;
	for(;b>=0;b=(b&(b+1))-1)ret+=bit[b];
	return ret;
}
void add(int a,int b){
	for(;a<110000;a|=(a+1))bit[a]+=b;
}
int main(){
	int a,b,c;scanf("%d%d%d",&a,&b,&c);
	for(int i=0;i<b;i++){
		int p;scanf("%d",&p);p--;
		add(p,1);
	}
	int ret=0;
	for(int i=c-1;i<a;i++){
		if(sum(i-c+1,i)<2){
			if(sum(i,i)){
				ret++;add(i-1,1);
			}else{
				ret++;add(i,1);
				if(sum(i-c+1,i)==1){
					ret++;add(i-1,1);
				}
			}
		}
	}
	printf("%d\n",ret);
}

F: Illumination
2-SAT.

vector<int>g[5100];
vector<int>rev[5100];
int v[5100]; // used twice
int num[5100]; // inverse of conv
int conv[5100]; // dfs order of i-th vertex. note that it's kaerigake ordered
int scc[5100]; // the index of scc containing i-th vertex
int fi[5100]; // the first element of each scc
int ss[5100]; // size of each scc
int cur;
void dfs(int a){
	for(int i=0;i<g[a].size();i++){
		if(v[g[a][i]])continue;
		v[g[a][i]]=1;
		dfs(g[a][i]);
	}
	conv[a]=cur;
	num[cur++]=a;
}
void dfs2(int a){
	scc[a]=cur;
	ss[cur]++;
	for(int i=0;i<rev[a].size();i++){
		if(v[rev[a][i]])continue;
		v[rev[a][i]]=1;
		dfs2(rev[a][i]);
	}
}


int x[1100];
int y[1100];
int main(){
	int a,b,c;
	scanf("%d%d%d",&a,&b,&c);
	for(int i=0;i<c;i++){
		scanf("%d%d",x+i,y+i);
	}
	for(int i=0;i<c;i++){
		for(int j=i+1;j<c;j++){
			if(x[i]==x[j]){
				if(ABS(y[i]-y[j])<=2*b){
					g[i*2].push_back(j*2+1);
					g[j*2].push_back(i*2+1);
					rev[i*2+1].push_back(j*2);
					rev[j*2+1].push_back(i*2);
					
				}
			}
			if(y[i]==y[j]){
				if(ABS(x[i]-x[j])<=2*b){
					g[i*2+1].push_back(j*2);
					g[j*2+1].push_back(i*2);
					rev[i*2].push_back(j*2+1);
					rev[j*2].push_back(i*2+1);
				}
			}
		}
	}
	for(int i=0;i<2*c;i++){
		if(v[i])continue;
		v[i]=1;
		dfs(i);
	}
	cur=0;
	for(int i=0;i<c*2;i++)v[i]=0;
	for(int i=c*2-1;i>=0;i--){
		if(v[num[i]])continue;
		v[num[i]]=1;
		fi[cur]=num[i];
		dfs2(num[i]);
		cur++;
	}
	for(int i=0;i<c;i++){
		if(scc[i*2]==scc[i*2+1]){
			printf("NO\n");return 0;
		}
	}
	printf("YES\n");
}

H: Paint
区間のことも頂点だと思う。

long long dp1[410000];
long long dp2[210000];
vector<pair<pair<long long,int> ,int> > ev;

int main(){
	long long a;
	int n;scanf("%I64d%d",&a,&n);
	for(int i=0;i<n;i++){
		long long p,q;scanf("%I64d%I64d",&p,&q);
		p--;
		ev.push_back(make_pair(make_pair(p,1),i));
		ev.push_back(make_pair(make_pair(q,0),i));
		
	}
	std::sort(ev.begin(),ev.end());
	for(int i=0;i<210000;i++)dp2[i]=inf;
	for(int i=0;i<410000;i++)dp1[i]=inf;
	long long now=0;
	long long cur=0;
	for(int i=0;i<ev.size();i++){
		int at=ev[i].second;
		long long ad=ev[i].first.first-now;
		now+=ad;cur+=ad;
		if(ev[i].first.second==1){
			dp2[at]=min(dp2[at],cur);
		}else{
			if(cur>dp2[at]){
				cur=dp2[at];
			}
		}
	}
	cur+=a-now;
	printf("%I64d\n",cur);
}

K: Tournament Wins
算数。

int main(){
	int a,b;scanf("%d%d",&a,&b);
	double ret=0;
	int rem=(1<<a)-b;
	int n=(1<<a);
	for(int i=0;i<a;i++){
		double ks=1;
		int t=(1<<(i+1))-1;
		if(t>rem){
			break;
		}
		for(int j=0;j<t;j++){
			ks*=(double)(rem-j)/(n-1-j);
		}
		ret+=ks;
	}
	printf("%.5f\n",ret);
}

I: Postman
Greedy.

pair<int,int>p[1100];
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		int s,t;scanf("%d%d",&s,&t);
		p[i]=make_pair(s,t);
	}std::sort(p,p+a);
	long long ret=0;
	int tmp=b;

	for(int i=0;i<a;i++){
		if(p[i].first>=0)break;
		if(tmp+p[i].second<=b){
			tmp+=p[i].second;continue;
		}
		int req=p[i].second;
		req-=b-tmp;
		int sk=req/b;
		ret+=(long long)(-p[i].first)*sk;
		req-=sk*b;
		if(req){
			tmp=req;
			ret+=(-p[i].first);
		}else{
			tmp=b;
		}
	}
	tmp=b;
	for(int i=a-1;i>=0;i--){
		if(p[i].first<=0)break;
		if(tmp+p[i].second<=b){
			tmp+=p[i].second;continue;
		}
		int req=p[i].second;
		req-=b-tmp;
		int sk=req/b;
		ret+=(long long)(p[i].first)*sk;
		req-=sk*b;
		if(req){
			tmp=req;
			ret+=(p[i].first);
		}else{
			tmp=b;
		}
	}
	printf("%I64d\n",ret*2);
}

B: Buggy Robot
がんばる

int bfs[60][60][60];
int dx[]={-1,1,0,0};
int dy[]={0,0,-1,1};
char dir[6]="UDLR";
char in[60][60];
char str[60];
int v[60][60][60];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%s",in[i]);
	}
	scanf("%s",str);
	int n=strlen(str);
	int sx,sy,gx,gy;
	for(int i=0;i<a;i++)for(int j=0;j<b;j++){
		if(in[i][j]=='R'){
			sx=i;sy=j;
		}
		if(in[i][j]=='E'){
			gx=i;gy=j;
		}
	}
	for(int i=0;i<a;i++)for(int j=0;j<b;j++)for(int k=0;k<=n;k++){
		bfs[i][j][k]=-1;
	}
	bfs[sx][sy][0]=0;
	deque<pair<pair<int,int>,int> >Q;
	Q.push_back(make_pair(make_pair(sx,sy),0));
	while(Q.size()){
		int row=Q.front().first.first;
		int col=Q.front().first.second;
		int at=Q.front().second;Q.pop_front();
		if(v[row][col][at])continue;
		v[row][col][at]=1;
		if(at<n){
			int tr=row;
			int tc=col;
			for(int i=0;i<4;i++)if(dir[i]==str[at]){
				tr+=dx[i];tc+=dy[i];
			}
			if(tr<0||tr>=a||tc<0||tc>=b||in[tr][tc]=='#'){
				tr=row;tc=col;
			}
			if(bfs[tr][tc][at+1]==-1||bfs[tr][tc][at+1]>bfs[row][col][at]){
				bfs[tr][tc][at+1]=bfs[row][col][at];
				Q.push_front(make_pair(make_pair(tr,tc),at+1));
			}
		}
		for(int i=0;i<4;i++){
			int tr=row+dx[i];
			int tc=col+dy[i];
			if(tr<0||tr>=a||tc<0||tc>=b||in[tr][tc]=='#'){
				tr=row;tc=col;
			}
			if(bfs[tr][tc][at]==-1){
				bfs[tr][tc][at]=bfs[row][col][at]+1;
				Q.push_back(make_pair(make_pair(tr,tc),at));
			}
		}
	}
	int ret=mod;
	for(int i=0;i<=n;i++)ret=min(ret,bfs[gx][gy][i]);
	printf("%d\n",ret);
}

J: Shopping
modで半分になるやつを Sparse Table で高速化。

long long p[210000];
long long st[20][262144];
int fnd(int a,long long b){
	int ret=a;
	for(int i=19;i>=0;i--){
		if(st[i][ret]>b){
			ret+=(1<<i);
		}
		if(ret>=262144)break;
	}
	return ret;
}
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%I64d",p+i);
	}
	for(int i=0;i<262144;i++){
		for(int j=0;j<20;j++)st[j][i]=inf;
	}
	for(int i=0;i<a;i++){
		st[0][i]=p[i];
	}
	for(int i=1;i<20;i++){
		for(int j=0;j<262144;j++){
			st[i][j]=min(st[i-1][j],j+(1<<(i-1))<262144?st[i-1][j+(1<<(i-1))]:inf);
		}
	}
	while(b--){
		long long v;
		int l,r;
		scanf("%I64d%d%d",&v,&l,&r);
		l--;
		int at=l;
		while(at<r){
			int to=fnd(at,v);
			if(to>=r){
				break;
			}
			v%=p[to];
			at=to;
		}
		printf("%I64d\n",v);
	}
}

L: Windy Path
絶対できる。次に正しく曲がるために一番角度がきついものを選ぶ。

Pt p[60];
int v[60];
char in[60];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a;i++){
		int X,Y;scanf("%d%d",&X,&Y);
		p[i]=Pt(X,Y)*Pt(cos(1),sin(1));
	}

	int st=0;
	for(int i=0;i<a;i++){
		if(p[i].x<p[st].x)st=i;
	}
	scanf("%s",in);
	printf("%d",st+1);
	v[st]=1;
	for(int i=0;i<a-1;i++){
		int to=0;
		if(in[i]=='R')to=1;
		int nx=0;
		for(int j=0;j<a;j++)if(!v[j])nx=j;
		if(to){ // 一番左を選ぶ
			for(int j=0;j<a;j++){
				if(v[j])continue;
				if(iSP(p[st],p[nx],p[j])==1)nx=j;
			}
		}else{ // 一番右を選ぶ
			for(int j=0;j<a;j++){
				if(v[j])continue;
				if(iSP(p[st],p[nx],p[j])==-1)nx=j;
			}
		}
		st=nx;
		v[st]=1;
		printf(" %d",st+1);
	}
	printf("\n");
}

G: Maximum Islands
すでにある陸の周りを海で塗って残りはフロー。LとWを間違えた(は?)。

int dx[]={1,0,-1,0};

int dy[]={0,1,0,-1};
char in[50][50];


const int D_MAX_V=5002;
const int D_v_size=5002;
struct D_wolf{
	int t,c,r;
	D_wolf(){t=c=r=0;}
	D_wolf(int t1,int c1,int r1){
		t=t1;c=c1;r=r1;
	}
};
vector<D_wolf>D_G[D_MAX_V];
int D_level[D_MAX_V];
int D_iter[D_MAX_V];

void add_edge(int from,int to,int cap){
	D_G[from].push_back(D_wolf(to,cap,D_G[to].size()));
	D_G[to].push_back(D_wolf(from,0,D_G[from].size()-1));
}
void D_bfs(int s){
	for(int i=0;i<D_v_size;i++)D_level[i]=-1;
	queue<int> Q;
	D_level[s]=0;
	Q.push(s);
	while(Q.size()){
		int v=Q.front();
		Q.pop();
		for(int i=0;i<D_G[v].size();i++){
			if(D_G[v][i].c>0&&D_level[D_G[v][i].t]<0){
				D_level[D_G[v][i].t]=D_level[v]+1;
				Q.push(D_G[v][i].t);
			}
		}
	}
}
int D_dfs(int v,int t,int f){
	if(v==t)return f;
	for(;D_iter[v]<D_G[v].size();D_iter[v]++){
		int i=D_iter[v];
		if(D_G[v][i].c>0&&D_level[v]<D_level[D_G[v][i].t]){
			int d=D_dfs(D_G[v][i].t,t,min(f,D_G[v][i].c));
			if(d>0){
				D_G[v][i].c-=d;
				D_G[D_G[v][i].t][D_G[v][i].r].c+=d;
				return d;
			}
		}
	}
	return 0;
}
int max_flow(int s,int t){
	int flow=0;
	for(;;){
		D_bfs(s);
		if(D_level[t]<0)return flow;
		for(int i=0;i<D_v_size;i++)D_iter[i]=0;
		int f;
		while((f=D_dfs(s,t,99999999))>0){flow+=f;}
	}
	return 0;
}
int UF[2000];
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 main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++)scanf("%s",in[i]);
	for(int i=0;i<a*b;i++)UF[i]=-1;
	for(int i=0;i<a;i++)for(int j=0;j<b;j++){
		if(in[i][j]=='L'){
			for(int k=0;k<4;k++){
				int tr=i+dx[k];
				int tc=j+dy[k];
				if(tr<0||tc<0||tr>=a||tc>=b)continue;
					if(in[tr][tc]=='C')in[tr][tc]='W';
					if(in[tr][tc]=='L'){
						UNION(i*b+j,tr*b+tc);
					}
				
			}
		}
	}
	int ret=0;
	for(int i=0;i<a;i++){
		for(int j=0;j<b;j++){
			if(in[i][j]=='L'&&FIND(i*b+j)==(i*b+j))ret++;
		}
	}
	int S=a*b;
	int T=a*b+1;
	int cnt=0;
	for(int i=0;i<a;i++)for(int j=0;j<b;j++){
		if(in[i][j]=='C'){
			cnt++;
			if((i+j)%2){
				add_edge(S,i*b+j,1);
				for(int k=0;k<4;k++){
					int tr=i+dx[k];
					int tc=j+dy[k];
					if(tr<0||tc<0||tr>=a||tc>=b)continue;
					if(in[tr][tc]=='C'){
						add_edge(i*b+j,tr*b+tc,1);
					}
				}
			}else{
				add_edge(i*b+j,T,1);
			}
		}
	}
	ret+=cnt-max_flow(S,T);
	printf("%d\n",ret);
}

D: Contest Strategy
ひさしぶりに非やるだけを解いた。
t番目の要素ごとに独立で、それぞれに対して dp[i][j][k]: i番目まで見てt番目より大きいものがj回出てきた、すでにt番目が出現したかどうか、を持てばよい。t番目を解くのは、jがK-1以上かつkが1になった最初のタイミング。

long long dp[310][310][2];
int p[310];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%d",p+i);
	}
	std::sort(p,p+a);
	long long ret=0;
	for(int i=0;i<a;i++){

		long long ks;
		if(a-i<b){
			ks=(a-i)*p[i];
			for(int j=1;j<=a;j++)ks=ks*j%mod;
		//printf("%lld\n",ks);
			ret=(ret+ks)%mod;
			continue;
		}
		ks=0;
		for(int j=0;j<=a;j++)for(int k=0;k<=a;k++)for(int l=0;l<2;l++)
			dp[j][k][l]=0;
		dp[0][0][0]=1;
		for(int j=0;j<a;j++){
			for(int k=0;k<a;k++){
				for(int l=0;l<2;l++){
					if(!dp[j][k][l])continue;
			//		printf("%d %d %d %d: %lld\n",i,j,k,l,dp[j][k][l]);
					if(l==0){
						dp[j+1][k][1]=(dp[j+1][k][1]+dp[j][k][l])%mod;
						if((a-1-i-k)>0)dp[j+1][k+1][0]=(dp[j+1][k+1][0]+dp[j][k][l]*(a-1-i-k))%mod;
						if(i+k-j>0)dp[j+1][k][0]=(dp[j+1][k][0]+dp[j][k][l]*(i+k-j))%mod;
					}else{
						if(k>=b-1)continue;
						
						if((a-1-i-k)>0)dp[j+1][k+1][1]=(dp[j+1][k+1][1]+dp[j][k][l]*(a-1-i-k))%mod;
						if(i+k-j+1>0)dp[j+1][k][1]=(dp[j+1][k][1]+dp[j][k][l]*(i+k-j+1))%mod;
					}
				}
			}
		}
		long long t=1;

		for(int j=a;j>=b;j--){
			for(int k=b-1;k<=a;k++){
				ks=(ks+dp[j][k][1]*(a-j+b)%mod*t)%mod;
			}
			t=t*(a-j+1)%mod;
		}
		ret=(ret+ks*p[i])%mod;
	//	printf("%lld\n",ks*p[i]%mod);
	}
	printf("%lld\n",ret);
}

E: Enclosure
絶対やばいと思うんですが...

ひとり地区予選 2014-2015 ACM-ICPC Southeast USA Regional

今日もひとりでRegiona練習。ICPC引退したはずなんですけどねぇ...。

E: Hill Number
こういうのはもういいよね。

int dp[20][3][2][10];
char in[20];
int main(){
    long long a;scanf("%lld",&a);

    dp[0][0][0][0]=1;
    sprintf(in,"%lld",a);
    int n=0;
    long long tmp=a;
    while(tmp){
        n++;
        tmp/=10;
    }
    bool ok=false;
    for(int i=0;i<n;i++){
        bool OK=true;
        for(int j=0;j<n-1;j++){
            if(in[j]>in[j+1]&&j<i)OK=false;
            if(in[j]<in[j+1]&&j>=i)OK=false;
        }
        if(OK)ok=true;
    }
    if(!ok){
        printf("-1\n");return 0;
    }
    long long ret=0;
    for(int i=0;i<n;i++){
        for(int j=0;j<3;j++)for(int k=0;k<2;k++)for(int l=0;l<10;l++){
            if(dp[i][j][k][l]==0)continue;
            for(int m=0;m<10;m++){
                if(i==0&&m==0)continue;
                int tj=j;
                if(tj==0){
                    if(in[i]-'0'>m){
                        tj=1;
                    }
                    if(in[i]-'0'<m){
                        tj=2;
                    }
                }
                int to=k;
                if(k==0){
                    if(m<l)to=1;
                }else{
                    if(m>l)to=-1;
                }
                if(to==-1)continue;
                dp[i+1][tj][to][m]+=dp[i][j][k][l];
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<3;j++){
            if(i==n&&j==2)continue;
            for(int k=0;k<2;k++)for(int l=0;l<10;l++){
                ret+=dp[i][j][k][l];
            }
        }
    }
    printf("%lld\n",ret);
}

F: Knights
こういうのももういいよね。

int dx[]={1,1,2,2};
int dy[]={-2,2,-1,1};
int t[10][10];
int main(){
    int a,b;scanf("%d%d",&a,&b);
    mat wolf;
    for(int i=0;i<(1<<(a*2));i++){
        for(int j=0;j<(1<<a);j++){
            bool ok=true;
            for(int k=0;k<a*2;k++){
                if(i&(1<<k)){
                    t[k/a][k%a]=1;
                }else t[k/a][k%a]=0;
            }
            for(int k=0;k<a;k++){
                if(j&(1<<k)){
                    t[2][k]=1;
                }else t[2][k]=0;
            }
            for(int k=0;k<2;k++){
                for(int l=0;l<a;l++){
                    if(t[k][l]){
                        for(int m=0;m<4;m++){
                            int tr=k+dx[m];
                            int tc=l+dy[m];
                            if(tr<3&&tc<a&&tc>=0&&t[tr][tc])ok=false;
                        }
                    }
                }
            }
            if(ok){
                wolf.a[(i>>a)+(j<<a)][i]++;
            }
        }
    }
    mat res=pw(wolf,b);
    long long ret=0;
    for(int i=0;i<(1<<(a*2));i++){
        ret=(ret+res.a[i][0])%mod;
    }
    printf("%lld\n",ret);
}

G: Word Ladder
Outputに細かい条件とかタイブレークの仕方とかを大量に並べるのほんまにやめてほしい

char in[1100][10];
int bfs[2][1100];
vector<int>g[1100];
int C[1100][1100];
char out[10];
char tmp[10];
int main(){
    int a;scanf("%d",&a);
    int len=0;
    for(int i=0;i<a;i++){
        scanf("%s",in[i]);
    }
    len=strlen(in[0]);
    for(int i=0;i<a;i++){
        for(int j=0;j<a;j++){
            if(i==j)continue;
            int cnt=0;
            for(int k=0;k<len;k++){
                if(in[i][k]!=in[j][k])cnt++;
            }
            C[i][j]=cnt;
            if(cnt==1){
                g[i].push_back(j);
            }
        }
    }
    if(C[0][1]==0){
        printf("0\n0\n");
        return 0;
    }
    for(int V=0;V<2;V++){
        for(int i=0;i<a;i++){
            bfs[V][i]=-1;
        }
        queue<int>Q;
        if(V==0){
            Q.push(0);
            bfs[V][0]=0;
        }else{
            Q.push(1);
            bfs[V][1]=0;
        }
        while(Q.size()){
            int at=Q.front();Q.pop();
            for(int i=0;i<g[at].size();i++){
                int to=g[at][i];
                if(bfs[V][to]==-1){
                    bfs[V][to]=bfs[V][at]+1;
                    Q.push(to);
                }
            }
        }
    }
    int dist=bfs[0][1];
    int ret=mod;
    for(int i=0;i<a;i++){
        for(int j=0;j<a;j++){
            if(i==j)continue;
            if(C[i][j]!=2)continue;
            if(bfs[0][i]==-1||bfs[1][j]==-1)continue;
            int cost=bfs[0][i]+bfs[1][j]+2;
            if(cost<=ret){
                
                int fi=0;
                for(int k=0;k<len;k++){
                    tmp[k]=in[i][k];
                    if(in[i][k]!=in[j][k]){
                        if(fi)tmp[k]=in[j][k];
                        fi++;
                    }
                }
                bool tok=true;
                if(cost==ret){
                    for(int k=0;k<len;k++){
                        if(out[k]!=tmp[k]){
                            if(out[k]>tmp[k])break;
                            if(out[k]<tmp[k]){
                                tok=false;
                                break;
                            }
                        }
                    }
                }
                if(tok){
                    for(int k=0;k<len;k++)out[k]=tmp[k];
                }
                ret=cost;
                fi=0;
                for(int k=0;k<len;k++){
                    tmp[k]=in[i][k];
                    if(in[i][k]!=in[j][k]){
                        if(fi==0)tmp[k]=in[j][k];
                        fi++;
                    }
                }
                tok=true;
                if(cost==ret){
                    for(int k=0;k<len;k++){
                        if(out[k]!=tmp[k]){
                            if(out[k]>tmp[k])break;
                            if(out[k]<tmp[k]){
                                tok=false;
                                break;
                            }
                        }
                    }
                }
                if(tok){
                    for(int k=0;k<len;k++)out[k]=tmp[k];
                }
            }
        }
    }
    if(dist==-1&&ret==mod){
        printf("0\n-1\n");return 0;
    }
    if(dist==-1)dist=mod;
    if(dist<=ret){
        printf("0\n%d\n",dist);return 0;
    }
    printf("%s\n%d\n",out,ret);
}

C: Containment
まず北米特有の無駄ストーリーのせいで問題文が読めない。虚無。

int main(){
    int a;scanf("%d",&a);
    int S=12*12*12;
    int T=12*12*12+1;
    for(int i=0;i<12;i++)for(int j=0;j<12;j++)for(int k=0;k<12;k++){
        if(i==0||i==11||j==0||j==11||k==0||k==11){
            add_edge(i*144+j*12+k,T,1);
        }
    }
    for(int i=0;i<12;i++)for(int j=0;j<12;j++)for(int k=0;k<11;k++){
        add_edge(i*144+j*12+k,i*144+j*12+k+1,1);
        add_edge(i*144+j*12+k+1,i*144+j*12+k,1);
        add_edge(i*144+j*1+k*12,i*144+j*1+k*12+12,1);
        add_edge(i*144+j*1+k*12+12,i*144+j*1+k*12,1);
        add_edge(i*1+j*12+k*144,i*1+j*12+k*144+144,1);
        add_edge(i*1+j*12+k*144+144,i*1+j*12+k*144,1);

    }
    for(int i=0;i<a;i++){
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        x++;y++;z++;
        add_edge(S,x*144+y*12+z,99999999);
    }
    printf("%d\n",max_flow(S,T));
}

H: Shuffles
1回シャッフルすると1~Nを順にたどるのに周回できる回数の最大値が二倍になるんだよね

int p[1100000];
int inv[1100000];
int main(){
    int a;scanf("%d",&a);
    for(int i=0;i<a;i++){
        scanf("%d",p+i);p[i]--;
        inv[p[i]]=i;
    }
    int cnt=0;
    for(int i=0;i<a-1;i++){
        if(inv[i]>inv[i+1])cnt++;
    }
    cnt++;
    int ret=0;
    int lim=1;
    while(lim<cnt){
        lim*=2;ret++;
    }
    printf("%d\n",ret);
}

D: Gold Leaf
無能なのでこういうのが一番楽しい

char in[200][200];
int R1,C1,R2,C2;
int comp(int a,int b,int c,int d){
    if(make_pair(make_pair(R1,C1),make_pair(R2,C2))>make_pair(make_pair(a,b),make_pair(c,d)))return 1;
    return 0;
}
int main(){
    int a,b;scanf("%d%d",&a,&b);
    for(int i=0;i<a;i++){
        scanf("%s",in[i+40]+40);
    }
    for(int i=0;i<200;i++)for(int j=0;j<200;j++){
        if(in[i][j]=='#')in[i][j]=1;
        else in[i][j]=0;
    }
    R1=C1=R2=C2=mod;

    for(int i=0;i<a-1;i++){
        int r1=i+1;
        int r2=i+1;
        int c1=1;
        int c2=b;
        if(comp(r1,c1,r2,c2)==0)continue;
        bool ok=true;
        for(int k=0;k<a;k++)for(int l=0;l<b;l++){
            int tk=k;
            tk=1+i+(i-k);
            int tl=l;
            if(in[k+40][l+40]+in[tk+40][tl+40]!=1)ok=false;
        }
        if(ok){
            R1=r1;R2=r2;C1=c1;C2=c2;
        }
    }
    for(int i=0;i<b-1;i++){
        int c1=i+1;
        int c2=i+1;
        int r1=1;
        int r2=a;
        if(comp(r1,c1,r2,c2)==0)continue;
        bool ok=true;
        for(int k=0;k<a;k++)for(int l=0;l<b;l++){
            int tk=k;
            int tl=l;
            tl=1+i+(i-l);
            if(in[k+40][l+40]+in[tk+40][tl+40]!=1)ok=false;
        }
        if(ok){
            R1=r1;R2=r2;C1=c1;C2=c2;
        }
    }
    for(int i=0;i<a;i++)for(int j=0;j<b;j++){
        if(i&&j)continue;
        int r1=i+1;
        int c1=j+1;
        int r2=i+1;
        int c2=j+1;
        bool ok=true;
        while(r2<a&&c2<b){
            if(in[r2-1+40][c2-1+40]==0)ok=false;
            r2++;c2++;
        }
        if(in[r2-1+40][c2-1+40]==0)ok=false;
        if(comp(r1,c1,r2,c2)==0)continue;
        for(int k=0;k<a;k++)for(int l=0;l<b;l++){
            if(k-l==i-j)continue;
            int tk=i+(l-j);
            int tl=j+(k-i);
            if(in[k+40][l+40]+in[tk+40][tl+40]!=1)ok=false;
        }
        if(ok){
            R1=r1;R2=r2;C1=c1;C2=c2;
        }
    }
    for(int i=0;i<a;i++)for(int j=0;j<b;j++){
        if(i<a-1&&j)continue;
        int r1=i+1;
        int c1=j+1;
        int r2=i+1;
        int c2=j+1;
        bool ok=true;
        while(r2>1&&c2<b){
            if(in[r2-1+40][c2-1+40]==0)ok=false;
            r2--;c2++;
        }
        if(in[r2-1+40][c2-1+40]==0)ok=false;
        if(comp(r1,c1,r2,c2)==0)continue;
    //  printf("%d %d %d %d\n",r1,c1,r2,c2);
        for(int k=0;k<a;k++)for(int l=0;l<b;l++){
            if(k+l==i+j)continue;
            int tk=i-(l-j);
            int tl=j+(i-k);
            if(in[k+40][l+40]+in[tk+40][tl+40]!=1)ok=false;
        }
        if(ok){
            R1=r1;R2=r2;C1=c1;C2=c2;
        }
    }
    printf("%d %d %d %d\n",R1,C1,R2,C2);
}

B: Stained Carpet
次元を落として比率だと思うのがいいと思う。

inline double dist(double x,double y){return sqrt(x*x+y*y);}
int main(){
    double A,B,C;
    scanf("%lf%lf%lf",&A,&B,&C);
    if(A>B)swap(A,B);
    if(B>C)swap(B,C);
    if(A>B)swap(A,B);
    if(B>C)swap(B,C);
//  swap(A,C);
    double left=0;
    double right=sqrt(3)/2;
    double left2=0;
    double right2=1;
    for(int i=0;i<300;i++){
        double M=(left+right)/2;
        left2=0;
        right2=1;
        for(int j=0;j<300;j++){
            double M2=(left2+right2)/2;
            double b=dist(M2,M);
            double c=dist(1-M2,M);
            if(b/c<B/C){
                left2=M2;
            }else right2=M2;
        }
        double a=dist(left2-0.5,M-sqrt(3)/2);
        double b=dist(M,left2);
        if(a/b<A/B){
            right=M;
        }else left=M;
    }
    double x=left2;
    double y=left;
    //printf("%.12f %.12f %.12f\n",x,y,sqrt(3)/2);
    if(ABS(x-0.5)-EPS>0.5-y/sqrt(3)){
        printf("-1.000\n");return 0;
    }
    double th=B/dist(x,y);
    printf("%f\n",sqrt(3)/4*th*th);
}

A,I: Iはどこかで見たことあると思うんだけどなぁ...

今日も自明しか解けなかった、だめですね

Yandex 2018 Qual

バーチャルをまたやった。

A: 本番もといた。

int b[110];
int main(){
	for(int i=0;i<10;i++){
		int p;scanf("%d",&p);b[p]++;
	}
	int t;scanf("%d",&t);
	while(t--){
		int ret=0;
		for(int i=0;i<6;i++){
			int p;scanf("%d",&p);ret+=b[p];
		}
		if(ret>=3)printf("Lucky\n");
		else printf("Unlucky\n");
	}
}

B: これは頑張るとしか言いようがない。

int p[300][300];
int ans[11000];
int ad[11000];
int at[11000];
int main(){
	int a;scanf("%d",&a);
	for(int i=0;i<a*2;i++){
		for(int j=0;j<a;j++){
			scanf("%d",&p[i][j]);
			ad[p[i][j]]+=j;
		}
	}
	for(int i=0;i<11000;i++)at[i]=-1;
	for(int i=1;i<=a*a;i++){
		if(ad[i]==0){
			int nt=0;
			for(int j=0;j<a*2;j++){
				if(p[j][0]==i){
					nt=j;
					for(int k=0;k<a;k++){
						ans[k]=p[j][k];
						at[p[j][k]]=k;
					}
					break;
				}
			}
			for(int j=0;j<a*2;j++){
				if(nt==j)continue;
				if(~at[p[j][0]]){
					for(int k=0;k<a;k++){
						ans[at[p[j][0]]+k*a]=p[j][k];
					}
				}
			}
			break;
		}
	}
	for(int i=0;i<a*a;i++){
		if(i)printf(" ");
		printf("%d",ans[i]);
	}printf("\n");
}

C: a^((a-1)^2).

long long pw(long long a,long long b){
	long long ret=1;
	while(b){
		if(b%2)ret=ret*a%mod;
		a=a*a%mod;
		b/=2;
	}
	return ret;
}
int main(){
	int a;scanf("%d",&a);
	printf("%d\n",(int)pw(a,(a-1)*(a-1)));
}

D: n個の棒で三角形が全く作れないように頑張ると長さの下界がO(Fib(n))になる話

long long p[310000];
pair<long long,int> q[310];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%I64d",p+i);
	}
	while(b--){
		int l,r;scanf("%d%d",&l,&r);l--;r--;
		if(r-l+1<3){
			printf("-1\n");continue;
		}
		int sz=0;
		for(int i=l;i<=r;i++){
			if(sz==100)break;
			q[sz++]=make_pair(p[i],i+1);
		}
		std::sort(q,q+sz);
		bool ok=false;
		for(int i=0;i<sz-2;i++){
			if(q[i].first+q[i+1].first>q[i+2].first){
				printf("%d %d %d\n",q[i].second,q[i+1].second,q[i+2].second);
				ok=true;break;
			}
		}
		if(!ok)printf("-1\n");
	}
}

E: しゃくとりするだけ

char in[20];
long long p[110000];
long long q[110000];
map<long long,int> m;
int tmp[110000];
int fla=0;
int main(){
	int a,b;
	scanf("%d%d",&a,&b);
	for(int i=0;i<a;i++){
		scanf("%s",in);
		long long cur=0;
		for(int j=0;in[j];j++){
			cur*=27;
			cur+=in[j]-'a'+1;
		}
		p[i]=cur;
	}
	for(int i=0;i<b;i++){
		scanf("%s",in);
		long long cur=0;
		for(int j=0;in[j];j++){
			cur*=27;
			cur+=in[j]-'a'+1;
		}
		q[i]=cur;
	}
	for(int i=0;i<b;i++){
		m[q[i]]=i;
	}
	long long ret=0;
	int at=-1;
	for(int i=0;i<a;i++){
		while(at<a&&fla<b){
			at++;
			if(at==a)break;
			if(m.count(p[at])==0)continue;
			tmp[m[p[at]]]++;
			if(tmp[m[p[at]]]==1)fla++;
		}
		ret+=a-at;
		if(m.count(p[i])){
			tmp[m[p[i]]]--;
			if(tmp[m[p[i]]]==0)fla--;
		}
	}
	printf("%I64d\n",ret);
}

F: は? と思ったけどこれ普通にDPするだけなんですか...たまげたなぁ。

ひとり地区予選 2014-2015 ACM-ICPC East Central North America

何問解こうが虚無に5時間を費やしたことに変わりはないセット...

B: A Cure for the Common Code
10万回見たような設定の問題...。強引に高速化した区間DPするだけ。

char in[1100];
int dp[510][510];
int lg10[510];
int kr[510][510];
int solve(int a,int b){
	if(dp[a][b]!=-1)return dp[a][b];
	if(a==b)return dp[a][b]=0;
	int ret=mod;
	ret=min(ret,solve(a+1,b)+1);
	ret=min(ret,solve(a,b-1)+1);
	for(int i=a+1;i<b;i++){
		ret=min(ret,solve(a,i)+solve(i,b));
	}
	for(int i=1;i<b-a;i++){
		if((b-a)%i)continue;
		if(kr[a][i]>=b-a){
			if(i>1)ret=min(ret,solve(a,a+i)+2+lg10[(b-a)/i]);
			else ret=min(ret,solve(a,a+i)+lg10[(b-a)/i]);
		}
	}
	//printf("%d %d: %d\n",a,b,ret);
	return dp[a][b]=ret;
}
int main(){
	int ts=0;
	for(int i=1;i<510;i++){
		int c=i;
		while(c){
			lg10[i]++;c/=10;
		}
	}
	while(1){
		scanf("%s",in);
		if(in[0]=='0')break;
		int n=strlen(in);
		for(int i=0;i<=n;i++)for(int j=0;j<=n;j++){
			dp[i][j]=-1;
		}
		for(int i=0;i<510;i++)for(int j=0;j<510;j++)kr[i][j]=0;
		for(int i=0;i<n;i++){
			for(int j=1;j<=n;j++){
				for(int k=i;k<n;k++){
					if(k-j>=i&&in[k]!=in[k-j]){
						break;
					}
					kr[i][j]++;
				}
			}
		}
		ts++;
		printf("Case %d: %d\n",ts,solve(0,n));
	}
}

D: Generalized Roman Numerals
これも強引に区間DPを高速化するだけ...setのinsertは重いのでバカみたいにやってはいけない。

char in[1100];
set<int>dp[62][62];

void calc(int a,int b){
	if(a==b)return;
	if(dp[a][b].size())return;
	if(a+1==b){
		if(in[a]=='I')dp[a][b].insert(1);
		if(in[a]=='V')dp[a][b].insert(5);
		if(in[a]=='X')dp[a][b].insert(10);
		if(in[a]=='L')dp[a][b].insert(50);
		if(in[a]=='C')dp[a][b].insert(100);
		
		return;
	}
	vector<int>can(5001);
	for(int i=a+1;i<b;i++){
		calc(a,i);
		calc(i,b);
		for(set<int>::iterator it=dp[a][i].begin();it!=dp[a][i].end();it++){
			for(set<int>::iterator it2=dp[i][b].begin();it2!=dp[i][b].end();it2++){
				int A=*it;
				int B=*it2;

				if(A>=B)can[A+B]=1;
				else can[B-A]=1;
			}
		}
	}
	for(int i=0;i<5001;i++)if(can[i])dp[a][b].insert(i);
}
int main(){
	int ts=0;
	while(1){
		scanf("%s",in);
		if(in[0]=='0')break;
		int n=strlen(in);
		for(int i=0;i<62;i++)for(int j=0;j<62;j++)dp[i][j].clear();
		calc(0,n);
		ts++;
		printf("Case %d:",ts);
		for(set<int>::iterator it=dp[0][n].begin();it!=dp[0][n].end();it++){
			printf(" %d",*it);
		}
		printf("\n");
	}
}

A: Continued Fractions
連分数展開された有理数の四則演算をするだけ。負がある嫌がらせつき。

int p[2][20];
long long bs[2];
long long bb[2];
long long gcd(long long a,long long b){
	while(a){
		b%=a;swap(a,b);
	}
	return b;
}
void output(long long bs,long long bb){
	long long g=gcd(ABS(bs),ABS(bb));
	bs/=g;bb/=g;
	if(bb<0){
		bb=-bb;bs=-bs;
	}
	vector<long long>ans;
	if(bs>=0){
		ans.push_back(bs/bb);
		bs%=bb;
	}else{
		int gb=0;
		while(bs<0){
			gb++;
			bs+=bb;
		}
		ans.push_back(-gb);
	}
	while(bs){
		swap(bs,bb);
		ans.push_back(bs/bb);
		bs%=bb;
	}
	for(int i=0;i<ans.size();i++){
		if(i)printf(" ");
		printf("%I64d",ans[i]);
	}
	printf("\n");
}
int main(){
	int ts=0;
	while(1){
		int a,b;scanf("%d%d",&a,&b);
		if(a==0)break;
		for(int i=0;i<a;i++){
			scanf("%d",&p[0][i]);
		}
		for(int i=0;i<b;i++){
			scanf("%d",&p[1][i]);
		}
		if(a>2){
			bb[0]=p[0][a-1];bs[0]=1;
			for(int i=a-2;i>0;i--){
				long long tmp=bb[0];
				bb[0]=p[0][i]*bb[0]+bs[0];
				bs[0]=tmp;
			}
			bs[0]+=bb[0]*p[0][0];
		}else if(a==2){
			bb[0]=p[0][1];
			bs[0]=p[0][1]*p[0][0]+1;
		}else{
			bb[0]=1;bs[0]=p[0][0];
		}
		if(b>2){
			bb[1]=p[1][b-1];bs[1]=1;
			for(int i=b-2;i>0;i--){
				long long tmp=bb[1];
				bb[1]=p[1][i]*bb[1]+bs[1];
				bs[1]=tmp;
			}
			bs[1]+=bb[1]*p[1][0];
		}else if(b==2){
			bb[1]=p[1][1];
			bs[1]=p[1][1]*p[1][0]+1;
		}else{
			bb[1]=1;bs[1]=p[1][0];
		}
		
		ts++;
		printf("Case %d:\n",ts);
		output(bs[0]*bb[1]+bs[1]*bb[0],bb[0]*bb[1]);
		output(bs[0]*bb[1]-bs[1]*bb[0],bb[0]*bb[1]);
		output(bs[0]*bs[1],bb[0]*bb[1]);
		output(bs[0]*bb[1],bb[0]*bs[1]);
	}
}

H: Time Warp
ストレスしかたまらない算数。パソコン甲子園でやれ

char in[10];
int main(){
	int T;scanf("%d",&T);
	for(int t=1;t<=T;t++){
		int deg;
		int h;
		scanf("%d%s%d",&deg,in,&h);
		printf("Case %d: ",t);
		if(in[0]=='t'){
			int nd=(360-h%12*30)-deg;
			while(nd<=0)nd+=360;
			double kr=(double)nd/5.5*60;
			int H=(int)(kr+0.5+EPS)/3600;
			int M=(int)(kr+0.5+EPS)/60%60;
			int S=(int)(kr+EPS+0.5)%60;
			H=h-H;
			if(M||S)H--;
			M=60-M;
			if(S)M--;
			if(M==60)M=0;
			
			S=60-S;
			if(S==60)S=0;
			if(H<=0)H+=12;
			printf("%d:%02d:%02d\n",H,M,S);	
		}else{

			int nd=deg-(360-h%12*30);
			while(nd<=0)nd+=360;
			double kr=(double)nd/5.5*60;
		//	printf("%d %f\n",nd,kr);
			int H=(int)(kr+0.5+EPS)/3600;
			int M=(int)(kr+0.5+EPS)/60%60;
			int S=(int)(kr+EPS+0.5)%60;
			H+=h;
			if(H>12)H-=12;
			printf("%d:%02d:%02d\n",H,M,S);	
		}
	}
}

C: Domiyahtzee!
ただひたすらシミュレーションするだけ。やみくもに面倒なだけ。

int p[5][5]; // id
int used[7][7];
int L[13];
int R[13];
int table[5][5];
int cl[5][5];
int Y=0;
int dice(vector<int>v){
	int ko[7];
	for(int i=0;i<7;i++)ko[i]=0;
	for(int i=0;i<v.size();i++)ko[v[i]]++;
	for(int i=1;i<=6;i++){
		if(ko[i]==5){
			Y++;
			if(Y>1)return 100;
			return 50;
		}
		if(ko[i]==4){
			return i*4;
		}
	}
	for(int i=1;i<=6;i++)for(int j=i+1;j<=6;j++){
		if((ko[i]==3&&ko[j]==2)||(ko[i]==2&&ko[j]==3)){
			return 25;
		}
	}
	for(int i=1;i<=6;i++){
		if(ko[i]==3)return 3*i;
	}
	for(int i=1;i<=2;i++){
		bool ok=true;
		for(int j=0;j<5;j++){
			if(!ko[i+j])ok=false;
		}
		if(ok)return 40;
	}
	for(int i=1;i<=3;i++){
		bool ok=true;
		for(int j=0;j<4;j++){
			if(!ko[i+j])ok=false;
		}
		if(ok)return 30;
	}
	return 0;
}
int calc(){
	for(int i=0;i<5;i++){
	//	for(int j=0;j<5;j++)printf("%d",table[i][j]);
	//	printf("\n");
	}int ret=0;
	Y=0;
	for(int i=0;i<5;i++){
		vector<int>tmp;
		for(int j=0;j<5;j++)tmp.push_back(table[i][j]);
		ret+=dice(tmp);
	}
	for(int i=0;i<5;i++){
		vector<int>tmp;
		for(int j=0;j<5;j++)tmp.push_back(table[j][i]);
		ret+=dice(tmp);
	}
	vector<int>tmp;
	for(int i=0;i<5;i++)tmp.push_back(table[i][i]);
	ret+=dice(tmp);
	for(int i=0;i<5;i++)tmp[i]=table[i][4-i];
	ret+=dice(tmp);
//	printf("%d\n",ret);
	return ret;
}
char in[2];
int main(){
	int T;scanf("%d",&T);
	for(int t=1;t<=T;t++){
		int pos=0;
		for(int i=0;i<5;i++)for(int j=0;j<5;j++)p[i][j]=-1;
		for(int i=0;i<7;i++)for(int j=0;j<7;j++)used[i][j]=0;
		for(int i=0;i<13;i++){
			while(p[pos/5][pos%5]!=-1){
				pos++;
			}
			scanf("%s",in);
			if(in[0]=='V'){
				int x,y;scanf("%d%d",&x,&y);
				p[pos/5][pos%5]=p[pos/5+1][pos%5]=i;
				table[pos/5][pos%5]=x;
				table[pos/5+1][pos%5]=y;
				
				L[i]=x;
				R[i]=y;
				used[min(x,y)][max(x,y)]=1;
			}else if(in[0]=='H'){
				int x,y;scanf("%d%d",&x,&y);
				p[pos/5][pos%5]=p[pos/5][pos%5+1]=i;
				table[pos/5][pos%5]=x;
				table[pos/5][pos%5+1]=y;
				
				L[i]=x;
				R[i]=y;
				used[min(x,y)][max(x,y)]=1;
			}else{
				int x;scanf("%d",&x);
				p[pos/5][pos%5]=i;
				table[pos/5][pos%5]=x;
				
				L[i]=x;
				R[i]=0;
			}
		}
		for(int i=0;i<5;i++)for(int j=0;j<5;j++)cl[i][j]=table[i][j];
		int ret=calc();
		for(int i=0;i<13;i++){
			if(R[i]==0)continue;
			for(int j=1;j<7;j++)for(int k=1;k<7;k++){
				if(used[j][k]||used[k][j])continue;
				bool fi=true;
				for(int m=0;m<5;m++)for(int l=0;l<5;l++){
					if(p[m][l]==i){
						if(fi)table[m][l]=j;
						else table[m][l]=k;
						fi=false;
					}
				}
				ret=max(ret,calc());
				for(int m=0;m<5;m++)for(int l=0;l<5;l++)table[m][l]=cl[m][l];
			}
		}
		printf("Case %d: %d\n",t,ret);
	}
}

E: Inspectors
あの最小費用流でハミルトン路の嘘解法が作れるやつそのまま。一番楽。

int d[110][110];
int main(){
	int T;scanf("%d",&T);
	for(int t=1;t<=T;t++){
		int a;scanf("%d",&a);

		MCF::init(a*2+2);
		for(int i=0;i<a;i++){
			for(int j=i+1;j<a;j++){
				int x;scanf("%d",&x);
				d[i][j]=d[j][i]=x;
			}
		}

		for(int i=0;i<a;i++){
			for(int j=0;j<a;j++){
				if(i==j)continue;
				MCF::ae(i,j+a,1,d[i][j]);
			}
		}
		int S=a*2;
		int T=a*2+1;
		for(int i=0;i<a;i++){
			MCF::ae(S,i,1,0);
			MCF::ae(a+i,T,1,0);
		}
		MCF::solve(S,T,a);
		printf("Case %d: %d\n",t,MCF::toc);
	}
}

F: Path of Least Persistence
グラフだと思えばまあ普通の簡単な問題。実装量は多いけど

int dx[]={0,-1,1,0};
int dy[]={1,0,0,-1};
char ds[7]="ENSW";
int DX[110][110];
int DY[110][110];
char in[110];
int v[110][110];
int used[110][110];
int H,W;
void dfs(int a,int b){
	if(DX[a][b]==0&&DY[a][b]==0){
		v[a][b]=0;return;
	}
	if(v[a][b]==-3){
		v[a][b]=-1;return;
	}
	v[a][b]=-3;
	int ta=a+DX[a][b];
	int tb=b+DY[a][b];
	if(ta<0||ta>=H||tb<0||tb>=W){
		v[a][b]=-1;return;
	}
	dfs(ta,tb);
	if(v[ta][tb]>=0)v[a][b]=v[ta][tb]+1;
	else{
		v[a][b]=-1;
	}
}
int main(){
	//int T;scanf("%d",&T);
	for(int t=1;;t++){
		int a,b;scanf("%d%d",&a,&b);
		H=a;W=b;
		if(a==0)break;
		for(int i=0;i<a;i++)for(int j=0;j<b;j++){
			if(i==a-1&&j==b-1){
				DX[i][j]=DY[i][j]=0;
				continue;
			}
			scanf("%s",in);
			int len=strlen(in);
		//	printf("%s\n",in);
			int r;
			if(len==2){
				r=in[0]-'0';
				for(int k=0;k<4;k++)if(in[1]==ds[k]){
					DX[i][j]=dx[k]*r;
					DY[i][j]=dy[k]*r;
				}
			}else{
				r=(in[0]-'0')*10+in[1]-'0';
				for(int k=0;k<4;k++)if(in[2]==ds[k]){
					DX[i][j]=dx[k]*r;
					DY[i][j]=dy[k]*r;
				}
			}
		}

		for(int i=0;i<a;i++)for(int j=0;j<b;j++)used[i][j]=0;
		for(int i=0;i<a;i++){
			for(int j=0;j<b;j++){
				v[i][j]=-2;
			}
		}
		for(int i=0;i<a;i++)for(int j=0;j<b;j++){
			if(v[i][j]==-2){
				dfs(i,j);
			}
		}
		int res=v[0][0];
		if(res==-1)res=mod;
		int ans=-1;
		int R=0;
		int C=0;
		int r=0;
		int dir=0;

		int nowr=0;
		int nowc=0;
		int cnt=0;

		while(1){
			if(nowr<0||nowr>=H||nowc<0||nowc>=W)break;
			if(used[nowr][nowc])break;
			used[nowr][nowc]=1;
			if(nowr==a-1&&nowc==b-1)break;
			for(int k=1;k<100;k++)for(int l=0;l<4;l++){
				int tdx=dx[l]*k;
				int tdy=dy[l]*k;
				if(tdx==DX[nowr][nowc]&&tdy==DY[nowr][nowc])continue;
				if(nowr+tdx<0||nowr+tdx>=a)continue;
				if(nowc+tdy<0||nowc+tdy>=b)continue;
				if(v[nowr+tdx][nowc+tdy]==-1)continue;
				int cost=cnt+1+v[nowr+tdx][nowc+tdy];
				if(make_pair(make_pair(res,make_pair(R,C)),make_pair(r,dir))>make_pair(make_pair(cost,make_pair(nowr,nowc)),make_pair(k,l))){
					res=cost;ans=1;R=nowr;C=nowc;r=k;dir=l;
				}
			}
			cnt++;
			int tor=nowr+DX[nowr][nowc];
			int toc=nowc+DY[nowr][nowc];
			nowr=tor;nowc=toc;
		}
		printf("Case %d: ",t);
		if(ans==-1){
			if(res<mod)printf("none %d\n",res);
			else printf("impossible\n");
		}else{
			printf("%d %d %d%c %d\n",R,C,r,ds[dir],res);
		}

	}
}

I: Watch, Man!
実 家 の よ う な 安 心 感
サ ハ 共 和 国 の 伝 統 芸 能
狼  の  習  性

共和国向け。壁がどうくっついていようがどうでもいい。壁を全列挙して交差判定してグラフ作って流すだけ。入力の仕方も心折ってくる。EPSが大きくても小さくても落ちる。

int can[110][110];
Pt gp[110];
int gl[110];
Pt ap[110];
int al[110];
Pt tmp[200];
int type[200];
Pt tang[200];
char in[2];
int main(){
	//int T;scanf("%d",&T);
	for(int t=1;;t++){
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		if(a+b+c==0)break;
		for(int i=0;i<110;i++)for(int j=0;j<110;j++)can[i][j]=0;
		vector<pair<Pt,Pt> > lseg;
		vector<pair<pair<Pt, double>,pair<double,double> > > cseg;
		for(int i=0;i<a;i++){
			int n;scanf("%d",&n);
			for(int j=0;j<n;j++){
				double X,Y;
				scanf("%lf%lf%s",&X,&Y,in);
				tmp[j]=Pt(X,Y);
				if(in[0]=='s')type[j]=1;
				else type[j]=2;
				if(type[j]==2){
					scanf("%lf%lf",&X,&Y);
					tang[j]=Pt(X,Y);
				}
			}
			tmp[n]=tmp[0];
			for(int j=0;j<n;j++){
				if(type[j]==1){
					lseg.push_back(make_pair(tmp[j],tmp[j+1]));
				}else{
					Pt M1=(tmp[j]+tmp[j+1])/2;
					Pt M2=M1+(tmp[j+1]-tmp[j])*Pt(0,1);
					Pt C1=tmp[j];
					Pt C2=tmp[j]+tang[j]*Pt(0,1);
					Pt cen=pLL(M1,M2,C1,C2);
					double r=(tmp[j]-cen).ABS();
					double th1=(tmp[j]-cen).arg();
					double th2=(tmp[j+1]-cen).arg();
					if(sig((tang[j]).det(tmp[j+1]-tmp[j]))<0)swap(th1,th2);
					if(th1>th2){
						cseg.push_back(make_pair(make_pair(cen,r),make_pair(th1,PI)));
						cseg.push_back(make_pair(make_pair(cen,r),make_pair(-PI,th2)));
					}else{
						cseg.push_back(make_pair(make_pair(cen,r),make_pair(th1,th2)));
					}
				}
			}
		}

		//for(int i=0;i<cseg.size();i++)printf("Pt = (%f, %f), r = %f, th = [%f, %f]\n",cseg[i].first.first.x,cseg[i].first.first.y,cseg[i].first.second,cseg[i].second.first,cseg[i].second.second);
		for(int i=0;i<b;i++){
			double X,Y;
			scanf("%lf%lf%d",&X,&Y,al+i);
			ap[i]=Pt(X,Y);
		}
		for(int i=0;i<c;i++){
			double X,Y;
			scanf("%lf%lf%d",&X,&Y,gl+i);
			gp[i]=Pt(X,Y);
		}
		for(int i=0;i<b;i++)for(int j=0;j<c;j++){
			Pt A=ap[i];
			Pt B=gp[j];
			bool ok=true;
			for(int k=0;k<lseg.size();k++){
				if(iSS(A,B,lseg[k].first,lseg[k].second)){ok=false;break;}
			}
			if(!ok)continue;
			for(int k=0;k<cseg.size();k++){
				double dist=dLP(A,B,cseg[k].first.first);
				if(dist-EPS>cseg[k].first.second)continue;
				pair<Pt,Pt> cro=pCL(cseg[k].first.first,cseg[k].first.second,A,B);
				double th1=(cro.first-cseg[k].first.first).arg();
				double th2=(cro.second-cseg[k].first.first).arg();
				if(iSP(A,cro.first,B)==2&&cseg[k].second.first<EPS+th1&&th1<EPS+cseg[k].second.second)ok=false;
				if(iSP(A,cro.second,B)==2&&cseg[k].second.first<EPS+th2&&th2<EPS+cseg[k].second.second)ok=false;
				
			}
		//	if(ok)printf("%d %d\n",i,j);
			if(ok)can[i][j]=1;
		}
		for(int i=0;i<D_MAX_V;i++){
			D_level[i]=D_iter[i]=0;
			D_G[i].clear();
		}
		int S=b+c;
		int T=b+c+1;
		int sum=0;
		for(int i=0;i<b;i++){
			add_edge(S,i,al[i]);
			sum+=al[i];
		}
		for(int i=0;i<b;i++)for(int j=0;j<c;j++){
			if(can[i][j]){
				add_edge(i,b+j,1);
			}
		}
		for(int i=0;i<c;i++){
			add_edge(b+i,T,gl[i]);
		}
		printf("Case %d: ",t);
		if(max_flow(S,T)==sum)printf("Yes\n");
		else printf("No\n");
	}
}

G: 意味不明

vepifanov異常すぎるだろ

トロントに行きたいけどGCJは無理そうだからDCJの対策をする狼。四日目。

lispp3 Small

Largeはあまりにも虚無なので無視。
Smallの重要な点は、stackの分散のうまい方法としては、余った部分と不足部分の両方をあつめてくることで、masterで過不足がうまくあっているかを判定できる。
ただしこの問題では問題依存なテクニックが多い(+が少ないときはmasterに送る長さが短くていいとか)ので、応用性に乏しい。
気をつけるべきこととしては、masterを用意する場合は全部で99スレッドになるので、配列長が10100000では足りない。10110000にすると足りる。
smallだからというのもあるが、そこまで罠が多い問題ではない。おすすめもしないけど。

int L_ind[10110000];
char L_ch[10110000];
char R_ch[10110000];
int R_ind[10110000];
int rsz[110];
int lsz[110];
int rind[110][310];
int lind[110][310];
char lst[110][310];
char rst[110][310];
int rnew[110];
int main(){
	int T=NumberOfNodes();
	int I=MyNodeId();
	int N=GetLength();
	if(I==T-1){
		int error=N;
		int perror=N;
		for(int i=0;i<T-1;i++){
			Receive(i);
			int tmp=GetInt(i);
			if(tmp!=-1)perror=min(perror,tmp);
			rnew[i]=GetInt(i);
			rsz[i]=GetInt(i);
			for(int j=0;j<rsz[i];j++){
				rind[i][rsz[i]-1-j]=GetInt(i);
				rst[i][rsz[i]-1-j]=GetCharacter(rind[i][rsz[i]-1-j]);
			}
			lsz[i]=GetInt(i);
			for(int j=0;j<lsz[i];j++){
				lind[i][j]=GetInt(i);
				lst[i][j]=GetCharacter(lind[i][j]);
			}
		}
		int R_sz=0;
		bool ed=false;
		bool R_new=true;
		int prev=-1;
		for(int i=0;i<T-1;i++){
			long long L=(long long)N*i/(T-1);
			long long R=(long long)N*(i+1)/(T-1);
			for(int j=0;j<lsz[i];j++){
				if(R_sz==0){
					error=lind[i][j];
					ed=true;break;
				}
				if(lind[i][j]>prev+1)R_new=false;
				prev=lind[i][j];
				if(lst[i][j]=='+'){
					if(!R_new&&R_ch[R_sz-1]=='('){
						R_ch[R_sz++]='+';
						R_new=true;
					}else{
						error=lind[i][j];ed=true;break;
					}
				}else{
					if((!R_new&&R_ch[R_sz-1]=='+')||(R_new&&R_ch[R_sz-1]=='(')){
						if(!R_new)R_sz-=2;
						else R_sz--;
						R_new=false;
					}else{
						error=lind[i][j];ed=true;break;
					}
				}

			}
			if(ed)break;
			for(int j=0;j<rsz[i];j++){
				if(rind[i][j]>prev+1)R_new=false;
				prev=rind[i][j];
				if(rst[i][j]=='('){
					R_ind[R_sz]=i;
					R_ch[R_sz++]=rst[i][j];
					R_new=true;
				}else if(rst[i][j]=='+'){
					if(!R_new&&R_ch[R_sz-1]=='('){
						R_ch[R_sz++]=rst[i][j];
						R_new=true;
					}
				}
			}
			if(ed)break;
		//	R_ch[R_sz]=0;printf("%d: %s\n",R_new,R_ch);
		}
		error=min(error,perror);
		if(error==N&&R_sz==0)error=-1;
		printf("%d\n",error);
	}else{
		long long L=(long long)N*I/(T-1);
		long long R=(long long)N*(I+1)/(T-1);
		int L_sz=0;
		int R_sz=0;
		bool R_new=false;
		int error=-1;
		for(int i=L;i<R;i++){
			char ch=GetCharacter(i);
			if(ch=='('){
				R_ind[R_sz]=i;
				R_ch[R_sz++]=ch;
				R_new=true;
			}else if(ch=='+'){
				if(R_sz==0){
					L_ind[L_sz]=i;
					L_ch[L_sz++]=ch;
				}else{
					if(!R_new&&R_ch[R_sz-1]=='('){
						R_ind[R_sz]=i;
						R_ch[R_sz++]=ch;
						R_new=true;
					}else{
						error=i;break;
					}
				}
			}else{
				if(R_sz==0){
					L_ind[L_sz]=i;
					L_ch[L_sz++]=ch;
				}else{
					if((!R_new&&R_ch[R_sz-1]=='+')||(R_new&&R_ch[R_sz-1]=='(')){
						if(R_ch[R_sz-1]=='+')R_sz-=2;
						else R_sz--;
						R_new=false;
					}else{
						error=i;break;
					}
				}
			}
		}
		PutInt(T-1,error);
		int se_t=0;
		if(R_new)se_t=1;
		PutInt(T-1,se_t);
		PutInt(T-1,min(210,R_sz));
		for(int i=0;i<min(210,R_sz);i++){
			PutInt(T-1,R_ind[R_sz-1-i]);
		}
		PutInt(T-1,min(210,L_sz));
		for(int i=0;i<min(210,L_sz);i++){
			PutInt(T-1,L_ind[i]);
		}
		R_ch[R_sz]=0;
		L_ch[L_sz]=0;
	//	printf("%s\n",R_ch);
	//	printf("%s\n",L_ch);
		
		Send(T-1);
	}

}

トロントに行きたいけどGCJは無理そうだからDCJの対策をする狼。三日目。

median

これも相当厄介(めんどくささが)。配列がランダムなことからハッシュが有効だというのがわかる。さらに、この問題ではかつてのプラクティスにあったshhhで使ったテクがかなり有効利用できる。
しかしいかんせん実装量が多くて複雑でテストが微妙なので、例によって通るかどうかヒヤヒヤな問題...。なんか一箇所変えたらACになったが。変えた場所がどういう意味を持ってるのかはわからん。
変なマジックナンバーを持ち出したいときはちゃんと素数をもってきましょう。

long long D=1000000000000000LL;
pair<wolf,long long> ev[1100];
int ps[1100];
wolf pk[1100];
int rn[1100000];
int vsz[1100];
int F=33000;
int cnt[40000];
int main(){
	int T=NumberOfNodes();
	int I=MyNodeId();
	if(I==T-1){
		for(int i=0;i<1000000;i++){
			rn[i]=GetData((long long)(xrand()%1000000000000000LL));
		}
		std::sort(rn,rn+1000000);
		int Cnt=0;
		for(int i=0;i<1000000;i++){
			if(i&&rn[i]==rn[i-1])Cnt++;
			else Cnt=1;
			if(Cnt>600000){
				printf("%d\n",rn[i]);
				for(int i=0;i<T-1;i++){
					PutInt(i,0);
					Send(i);
				}
				return 0;
			}
		}
		for(int i=0;i<T-1;i++){
			PutInt(i,1);
			Send(i);
		}
		int NK=1000;
		for(int i=0;i<NK;i++){
			long long st=i*1000037;
			wolf key=0;
			wolf ks=1;
			wolf mul=1145141919;
			for(int j=0;j<100;j++){
				key*=mul;
				ks*=mul;
				key+=GetData(D+st+j);
			}
			ev[i]=make_pair(key,st);
		}
		std::sort(ev,ev+NK);
		int sz=0;
		for(int i=0;i<NK;i++){
			if(i==0||ev[i].first!=ev[i-1].first){
				pk[sz]=ev[i].first;
				ps[sz]=ev[i].second;
				sz++;
			}
		}
		for(int i=0;i<T-1;i++){
			PutInt(i,sz);
			for(int j=0;j<sz;j++){
				PutLL(i,pk[j]);
				PutLL(i,ps[j]);
			}
			Send(i);
		}
		long long tot=0;
		for(int i=0;i<T-1;i++){
			Receive(i);
			for(int j=0;j<33000;j++){
				int tmp=GetInt(i);
				cnt[j]+=tmp;
				tot+=tmp;
			}
		}
		long long now=0;
		int pind=0;
		int qind=0;
		for(int i=0;i<33000;i++){
			now+=cnt[i];
			if(now*2>tot){
				pind=i;
				now-=cnt[i];
				break;
			}
		}
		for(int i=0;i<T-1;i++){
			PutInt(i,pind);
			Send(i);
		}
		//tot=0;
		for(int i=0;i<33000;i++)cnt[i]=0;
		for(int i=0;i<T-1;i++){
			Receive(i);
			for(int j=0;j<33000;j++){
				int tmp=GetInt(i);
				cnt[j]+=tmp;
				//tot+=tmp;
			}
		}
		//now=0;
		for(int i=0;i<33000;i++){
			now+=cnt[i];
			if(now*2>tot){
				qind=i;break;
			}
		}
		printf("%d\n",pind*33000+qind);
	}else{
		Receive(T-1);
		int ch=GetInt(T-1);
		if(ch==0)return 0;
		Receive(T-1);
		int sz=GetInt(T-1);
		for(int i=0;i<sz;i++){
			pk[i]=GetLL(T-1);
			ps[i]=GetLL(T-1);
		}
		wolf key=0;
		wolf ks=1;
		wolf mul=1145141919;
		for(int i=0;i<100;i++){
			key*=mul;
			ks*=mul;
			key+=GetData(D+i);
		}
		long long ind=0;
		long long os=0;
		while(1){
			int at=lower_bound(pk,pk+sz,key)-pk;
			if(pk[at]==key){
	//			printf("%d %lld\n",ps[at],ind);
				os=ps[at]-ind;
				break;
			}
			key*=mul;
			key+=GetData(D+ind+100);
			key-=ks*GetData(D+ind);
			ind++;
		}
	//	printf("%lld\n",(os+11)%11);
		int L=sz*I/(T-1);
		int R=sz*(I+1)/(T-1);
		for(int i=L;i<R;i++){
			key=0;
			ks=1;
			mul=1145141919;

			for(int j=0;j<100;j++){
				key*=mul;
				ks*=mul;
				key+=GetData(D+ps[i]-os+j);
			}
			while(1){
				key*=mul;
				key+=GetData(D+ps[i]-os+vsz[i]+100);
				int tmp=GetData(D+ps[i]-os+vsz[i]);
				cnt[tmp/F]++;
				key-=ks*tmp;
				vsz[i]++;
				if(binary_search(pk,pk+sz,key)){
					break;
				}
			}
		}
		for(int i=0;i<33000;i++){
			PutInt(T-1,cnt[i]);
		}
		Send(T-1);
		for(int i=0;i<33000;i++)cnt[i]=0;
		Receive(T-1);
		int tar=GetInt(T-1);
		for(int i=L;i<R;i++){
			for(int j=0;j<vsz[i];j++){
				int tmp=GetData(D+ps[i]-os+j);
		//		printf("%d %lld\n",i,((ps[i]+j)%17+17)%17);
				if(tmp/F==tar)cnt[tmp%F]++;
			}
		}
		for(int i=0;i<33000;i++){
			PutInt(T-1,cnt[i]);
		}
		Send(T-1);
	}
}