tozangezan's diary

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

2009 Starry Sky

Starry Sky木のもとになった問題なので当然Starry Sky木を使いますが、自明にO(N^2log N)が出てくるとして、問題はこれを定数倍改善しないと通らないということです。
このO(N^2 log N)は座標圧縮のところあたりが悪いのか、50点分しか取れないのでSegmentTree書くだけ無駄感がありますが、多分座標圧縮とかを改善するとはやくなるとおもいます。最悪ケースだと20sec程度。

#include<stdio.h>
#include<algorithm>
using namespace std;
int segtree[16384];
int L[4000];
unsigned int X[8000];
unsigned int B[4000];
unsigned int C[4000];
unsigned int D[4000];
void query(int a,int b,int c,int d,int e,int f){
	if(d<a||b<c)return;
	if(c<=a&&b<=d){
		segtree[e]+=f;
	}else{
		query(a,(a+b)/2,c,d,e*2,f);
		query((a+b)/2+1,b,c,d,e*2+1,f);
	}
	if(e==1){
//		printf("%d %d\n",e,segtree[e]);
		return;
	}
	if(segtree[e]>0||segtree[e^1]>0){
		int k=max(segtree[e],segtree[e^1]);
		segtree[e/2]+=k;
		segtree[e]-=k;
		segtree[e^1]-=k;
	}else if(segtree[e]<0&&segtree[e^1]<0){
		int k=max(segtree[e],segtree[e^1]);
		segtree[e/2]+=k;
		segtree[e]-=k;
		segtree[e^1]-=k;
	}
//	printf("%d %d\n",e,segtree[e]);
}
pair<pair<unsigned int,int>,pair<unsigned int,unsigned int> >event[8000];//Y TYPE X1 X2
int main(){
	int a;
	scanf("%d",&a);
	for(int i=0;i<a;i++){
		scanf("%u%u%u",B+i,C+i,D+i);
		B[i]*=2;
		C[i]*=2;
		D[i]*=2;
		L[i]=-((int)D[i]);
		
	}
	std::sort(L,L+a);
	int ret=0;
	for(int i=0;i<a;i++){
		int size=0;
		int now=0;
		unsigned int p=(unsigned int)(-L[i]);
		for(int j=0;j<a;j++){
			if(p<=D[j]){
				if(B[j]>=p/2)X[now++]=B[j]-p/2;
				else X[now++]=0;
				X[now++]=B[j]+p/2;
				if(C[j]>=p/2)event[size++]=make_pair(make_pair(C[j]-p/2,0),make_pair(X[now-2],X[now-1]));
				else event[size++]=make_pair(make_pair(0,0),make_pair(X[now-2],X[now-1]));
				event[size++]=make_pair(make_pair(C[j]+p/2,1),make_pair(X[now-2],X[now-1]));
			}
		}
		std::sort(X,X+now);
		std::sort(event,event+size);
		
		for(int i=0;i<size;i++){
			if(!event[i].first.second){
				query(0,8191,lower_bound(X,X+now,event[i].second.first)-X,lower_bound(X,X+now,event[i].second.second)-X,1,1);
			}else{
				query(0,8191,lower_bound(X,X+now,event[i].second.first)-X,lower_bound(X,X+now,event[i].second.second)-X,1,-1);
			}
			ret=max(ret,segtree[1]);
		}
	}
	printf("%d\n",ret);
}

意外と短くかけます。