tozangezan's diary

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

AOJ 2622: Removing Magical Tiles

追記:えっとパスの長さだから本当は下の図の0~5のところは1個多いですね
かなり解法が面白かったので解法を1枚の画像にしました。

f:id:tozangezan:20150613185404p:plain

#include<stdio.h>
#include<algorithm>
using namespace std;
int l1[110000];
int r1[110000];
int l2[110000];
int r2[110000];
int segtree[524288];
int dp[110000];
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+=262144;
	while(a){
		segtree[a]=max(segtree[a],b);
		a/=2;
	}
}
pair<int,pair<int,int> >ev[210000];
int z[210000];
int main(){
	int a;
	scanf("%d",&a);
	for(int i=0;i<a;i++){
		scanf("%d%d%d%d",l1+i,r1+i,l2+i,r2+i);
		z[i*2]=r2[i];
		z[i*2+1]=l2[i];
		ev[i*2]=make_pair(l1[i],make_pair(i,0));
		ev[i*2+1]=make_pair(r1[i],make_pair(i,1));
	}
	std::sort(z,z+a*2);
	std::sort(ev,ev+a*2);
	for(int i=0;i<a*2;i++){
		int at=ev[i].second.first;
		if(ev[i].second.second==0){
			int pos=lower_bound(z,z+a*2,l2[at])-z;
			dp[at]=query(0,262143,0,pos,1)+1;
		}else{
			int pos=lower_bound(z,z+a*2,r2[at])-z;
			update(pos,dp[at]);
		}
	}
	int ret=0;
	for(int i=0;i<a;i++)ret=max(ret,dp[i]);
	printf("%d\n",ret);
}