GCJ2013 Round 2

A-Large,B-Largeで通過です

A:座標圧縮とか、変な計算とか、面倒なことが多いだけ。

#include<stdio.h>
#include<algorithm>
using namespace std;
int d[1000];
int e[1000];
int f[1000];
int zahyou[2000];
long long v[2000];
int mod=1000002013;
int main(){
	int T;
	scanf("%d",&T);
	for(int t=1;t<=T;t++){
		int a,b,c;
		scanf("%d%d",&a,&b);
		for(int i=0;i<b;i++)scanf("%d%d%d",d+i,e+i,f+i);
		long long wolf=0;
		for(int i=0;i<b;i++){
			wolf=(wolf+(long long)f[i]*a%mod*(e[i]-d[i])%mod-(long long)f[i]*(e[i]-d[i]-1)%mod*(e[i]-d[i])%mod*500001007%mod+mod)%mod;
		}
		for(int i=0;i<b;i++){
			zahyou[i*2]=d[i];
			zahyou[i*2+1]=e[i]+1;
		}
		std::sort(zahyou,zahyou+b*2);
		for(int i=0;i<2000;i++)v[i]=0;
		long long ret=0;
		for(int i=0;i<b;i++){
			int L=upper_bound(zahyou,zahyou+b*2,d[i])-zahyou-1;
			int R=lower_bound(zahyou,zahyou+b*2,e[i]+1)-zahyou;
			for(int j=L;j<R;j++)v[j]+=f[i];
		}
		for(int i=0;i<2*b;i++){
			int at=-1;
			long long MIN=99999999999999LL;
			for(int j=0;j<2*b;j++){
				if(v[j]&&MIN>v[j]){
					MIN=v[j];
					at=j;
				}
			}
			if(!(~at))break;
			int L=at;
			int R=at;
			while(1){
				if(L&&v[L-1])L--;
				else break;
			}
			while(1){
				if(R<2*b-1&&v[R+1])R++;
				else break;
			}
			int dist=zahyou[R+1]-zahyou[L];
		//	printf("%lld %d %d\n",MIN,a,dist);
			ret=(ret+MIN*a%mod*(dist-1)%mod-MIN*(dist-1)%mod*(dist-2)%mod*500001007%mod+mod)%mod;
			for(int i=L;i<=R;i++)v[i]-=MIN;
		}
		printf("Case #%d: %lld\n",t,(wolf-ret+mod)%mod);
	}
}

B:二分探索するだけ。

#include<stdio.h>
#include<algorithm>
using namespace std;
int main(){
	int T;
	scanf("%d",&T);
	for(int t=1;t<=T;t++){
		int a;
		long long b;
		scanf("%d%lld",&a,&b);b--;
		long long left=0;
		long long right=(1LL<<a);
		while(left+1<right){
			long long M=(left+right)/2;
			long long ue=M;
			long long shita=(1LL<<a)-1-M;
			bool ok=true;
			for(int i=a-1;i>=0;i--){
				if(!(b&(1LL<<i))){
					if(ue){
						ok=false;
						break;
					}
					long long gen=(ue)/2;
					ue-=gen;
					shita-=(1LL<<i)-gen;
				}else{
					if(!ue){
						ok=true;
						break;
					}
					ue--;
					long long gen=1;
					gen+=(ue+1)/2;
					ue-=(ue+1)/2;
					shita-=(1LL<<i)-gen;
				}
			}
			if(ok)left=M;
			else right=M;
		}
		printf("Case #%d: %lld ",t,left);
		left=0;
		right=(1LL<<a);
		while(left+1<right){
			long long M=(left+right)/2;
			long long ue=M;
			long long shita=(1LL<<a)-1-M;
			bool ok=true;
			for(int i=a-1;i>=0;i--){
				if(!(b&(1LL<<i))){
					if(!shita){
						ok=false;
						break;
					}
					long long gen=1;
					shita--;
					gen+=(shita+1)/2;
					shita-=(shita+1)/2;
					ue-=(1LL<<i)-gen;
				}else{
					if(shita){
						ok=true;
						break;
					}
					long long gen=0;
					gen+=(shita)/2;
					shita-=(shita)/2;
					ue-=(1LL<<i)-gen;
				}
			}
			if(ok)left=M;
			else right=M;
		}
		printf("%lld\n",left);
	}
}

39pts 280th
これは次どう考えても通らないですね・・・ レーティングもないことだし、Round3は遊びます。