1. 程式人生 > >【線段樹】hdu6183 Color it

【線段樹】hdu6183 Color it

等於 light std 不同 所有 mem true 數據結構 三種

題意:

維護一個數據結構,支持三種操作:

①在平面上(x,y)處添加一個顏色為c的點。

②詢問平面上(1,y1)-(x,y2)範圍內,有多少種不同顏色的點。

③清除平面上所有點。

顏色數量很少,對於每種顏色分別建立線段樹,然後用線段樹維護y坐標,對每個y坐標只存下來x坐標最小的點的x坐標,然後每次詢問相當於問你[y1,y2]區間的最小值是否小於等於x。

卡常數,必須用動態開點線段樹,並且在詢問的時候進行剪枝(在區間內如果遇到了滿足條件的子區間,直接返回true,不繼續檢查其他子區間了)。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int INF=2147483647;
int root[55],lc[4000005],rc[4000005],v[4000005];  
int tot;
void newnode(int &rt){
	rt=++tot;
	lc[rt]=rc[rt]=0;
	v[rt]=INF;
}
void update(int p,int x,int &rt,int l,int r){
	if(!rt){
		newnode(rt);
 	}  
	if(l==r){
		v[rt]=min(v[rt],x);
		return;
	}
	int m=(l+r>>1);  
	if(p<=m){
		update(p,x,lc[rt],l,m);
	}
	else{
		update(p,x,rc[rt],m+1,r);
	}
	v[rt]=min(v[lc[rt]],v[rc[rt]]);
}
bool query(int x,int ql,int qr,int rt,int l,int r)  
{
	if(!rt){
		return 0;
	}
	if(ql<=l && r<=qr){
		if(v[rt]<=x){
			return 1;
		}
		return 0;
    }
	int m=(l+r>>1);
	if(ql<=m){
		if(query(x,ql,qr,lc[rt],l,m)){
			return 1;
		}
	}
	if(m<qr){
		if(query(x,ql,qr,rc[rt],m+1,r)){
			return 1;
		}
	}
	return 0;
}
int main()  
{
//	freopen("b.in","r",stdin);
	int op,x,y,z;
	v[0]=INF;
	while(1){
		scanf("%d",&op);
		if(op==3){
			break;
		}
		if(op==0){
			memset(root,0,sizeof(root));
			tot=0;
		}
		else if(op==1){
			scanf("%d%d%d",&x,&y,&z);
			update(y,x,root[z],1,1000000);
		}
		else if(op==2){
			scanf("%d%d%d",&x,&y,&z);
			int ans=0;
			for(int i=0;i<=50;++i){
				ans+=query(x,y,z,root[i],1,1000000);
			}
			printf("%d\n",ans);
		}
	}
    return 0;  
}  

【線段樹】hdu6183 Color it