tozangezan's diary

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

Codeforces Round #366 (Div. 1)

コンテストのバランスを全く考えていない難問セットなのですが、一つ一つはICPCの大変な問題(しかもサンプルも弱い)のような存在で、ただ実装が辛いだけでした。
ちなみにMARVELはヴェノム派です。

A B C D E Place
00:16 (+1) 00:53 (+3) - - - 33rd

A:
なんて事はないやるだけ問題なのですが、iとnumを1箇所間違えました。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<stdlib.h>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int p[310000];
int at[310000];
vector<int>v[310000];
int main(){
	int a,b;scanf("%d%d",&a,&b);
	int cnt=0;
	int ind=0;
	int num=0;
	for(int i=0;i<b;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		if(x==1){
			cnt++;
			v[y].push_back(num++);
		}else if(x==2){
			while(at[y]<v[y].size()){
				if(!p[v[y][at[y]]])cnt--;
				p[v[y][at[y]]]=1;
				at[y]++;
			}
		}else{
			while(ind<y){
				if(!p[ind])cnt--;
				p[ind]=1;
				ind++;
			}
		}
		printf("%d\n",cnt);
	}
}

B:
類題はもう何個もあると思います。生きている辺が1本のときの場合分けとかが厄介ですが、サンプルには入っていません。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<stdlib.h>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int x[5100];
long long dp[2][10100];
int A[5100];
int B[5100];
int C[5100];
int D[5100];

int main(){
	int a,b,c;
	scanf("%d%d%d",&a,&b,&c);
	b--;c--;
	for(int i=0;i<a;i++)scanf("%d",x+i);
	x[a]=mod;
	for(int i=0;i<a;i++)scanf("%d",A+i);
	for(int i=0;i<a;i++)scanf("%d",B+i);
	for(int i=0;i<a;i++)scanf("%d",C+i);
	for(int i=0;i<a;i++)scanf("%d",D+i);
	for(int i=0;i<2;i++)for(int j=0;j<10100;j++)dp[i][j]=inf;
	dp[0][0]=0;
	for(int i=0;i<a;i++){
		int t=i%2;
		for(int j=0;j<10100;j++)dp[!t][j]=inf;
		for(int j=0;j<a*2;j++){
			if(dp[t][j]==inf)continue;
			if(i==b){
				if(j>1||(j==1&&i==a-1))dp[!t][j-1]=min(dp[!t][j-1],dp[t][j]+(long long)(j-1)*(x[i+1]-x[i])+C[i]);
				dp[!t][j+1]=min(dp[!t][j+1],dp[t][j]+(long long)(j+1)*(x[i+1]-x[i])+D[i]);
			}else if(i==c){
				if(j>1||(j==1&&i==a-1))dp[!t][j-1]=min(dp[!t][j-1],dp[t][j]+(long long)(j-1)*(x[i+1]-x[i])+A[i]);
				dp[!t][j+1]=min(dp[!t][j+1],dp[t][j]+(long long)(j+1)*(x[i+1]-x[i])+B[i]);
			}else{
				dp[!t][j+2]=min(dp[!t][j+2],dp[t][j]+(long long)(j+2)*(x[i+1]-x[i])+B[i]+D[i]);
				if(j>1)dp[!t][j]=min(dp[!t][j],dp[t][j]+(long long)j*(x[i+1]-x[i])+min(B[i]+C[i],A[i]+D[i]));
				else if(j==1){
					if(b<i)dp[!t][j]=min(dp[!t][j],dp[t][j]+(long long)j*(x[i+1]-x[i])+A[i]+D[i]);
					else dp[!t][j]=min(dp[!t][j],dp[t][j]+(long long)j*(x[i+1]-x[i])+C[i]+B[i]);
				}
				if(j>2||(j==2&&i==a-1))dp[!t][j-2]=min(dp[!t][j-2],dp[t][j]+(long long)(j-2)*(x[i+1]-x[i])+A[i]+C[i]);
			}
		}
	}
	printf("%I64d\n",dp[a%2][0]);
}

C:
¬とかを無視すれば輪と直線しかないので、一次元にできてあとはありがちなDPをするだけですが、結構実装量が多いです。

#include<stdio.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<string.h>
#include<vector>
#include<set>
#include<map>
#include<stdlib.h>
using namespace std;
const long long mod=1000000007;
const long long inf=mod*mod;
int L[110000];
int R[110000];
vector<int>g[110000];
int ABS(int a){
	return max(a,-a);
}
int num=1;
int ord[110000];
int lm[110000];
int v[110000];
pair<int,int> p[110000];
long long dp[110000][2][2][2];
vector<int>q[110000];
int main(){
	int a,b;scanf("%d%d",&b,&a);
	for(int i=0;i<b;i++){
		int x;scanf("%d",&x);
		if(x==1){
			scanf("%d",L+i);
		}else{
			scanf("%d%d",L+i,R+i);
		//	if(ABS(L[i])<ABS(R[i]))swap(L[i],R[i]);
			if(ABS(L[i])!=ABS(R[i])){
				g[ABS(L[i])].push_back(ABS(R[i]));
				g[ABS(R[i])].push_back(ABS(L[i]));
			}
		}
	}
	for(int i=1;i<=a;i++)v[i]=-1;
	for(int i=1;i<=a;i++)p[i]=make_pair(g[i].size(),i);
	std::sort(p+1,p+a+1);
	for(int i=1;i<=a;i++){
		int at=p[i].second;
		if(~v[at])continue;
		int id=at;
		int tl=num;
		if(p[i].first!=2)tl=-1;

		while(1){
			bool ok=false;
			ord[num]=id;
			v[id]=num++;
			lm[id]=tl;
			for(int j=0;j<g[id].size();j++){
				if(~v[g[id][j]])continue;
				ok=true;
				id=g[id][j];
				break;
			}
			if(!ok)break;
		}
	}
	for(int i=0;i<b;i++){
		q[max(v[ABS(L[i])],v[ABS(R[i])])].push_back(i);
	}
//	for(int i=1;i<=a;i++)printf("%d ",v[i]);
//	printf("\n");
	dp[0][0][0][0]=1;
	for(int i=0;i<a;i++){
		for(int j=0;j<2;j++)for(int k=0;k<2;k++)for(int l=0;l<2;l++){
			if(!dp[i][j][k][l])continue;
			for(int m=0;m<2;m++){
				int tl=l;
				int tk=m;
				int tj=j;
				if(lm[ord[i+1]]==i+1)tj=m;

				for(int t=0;t<q[i+1].size();t++){
					int ql=L[q[i+1][t]];
					int qr=R[q[i+1][t]];
					if(ABS(ql)==ord[i+1]){
						if(qr==0){
							if(ql>0&&m)tl^=1;
							if(ql<0&&!m)tl^=1;
						}else if(ABS(qr)==ord[i+1]){
							if(((ql<0)^m)||((qr<0)^m))tl^=1;
						}else if(ABS(qr)==ord[i]){
							if(((ql<0)^m)||((qr<0)^k))tl^=1;
						}else{
							if(((ql<0)^m)||((qr<0)^j))tl^=1;
						}
					}else{
						if(ABS(ql)==ord[i]){
							if(((qr<0)^m)||((ql<0)^k))tl^=1;
						}else{
							if(((qr<0)^m)||((ql<0)^j))tl^=1;
						}
					}
				}
				dp[i+1][tj][tk][tl]=(dp[i+1][tj][tk][tl]+dp[i][j][k][l])%mod;
			}
		}
	}
	long long ret=0;
	for(int i=0;i<2;i++)for(int j=0;j<2;j++)ret+=dp[a][i][j][1];
	ret%=mod;
	printf("%d\n",(int)ret);
}