POJ 2777 线段树+lazy思想 + 染色问题

来源:互联网 发布:苹果系统小说软件 编辑:程序博客网 时间:2024/05/04 18:07

来源:http://poj.org/problem?id=2777

题意:有一个区间,最多有30种颜色。有两种操作,一种是对某一个区间段染上某一种颜色,一种是询问该区间有多少种不同的颜色。

思路:线段树的好题,线段树 + lazy思想的经典应用。而且和位运算结合到了一起。因为颜色数量很少,而且父结点的颜色正好是两个子结点颜色的按位或,因此可以用位运算。最后1的个数就是不同颜色的个数。

ac代码:

#include <iostream>#include <cstdio>using namespace std;const int N=100010;struct tree{int left,right,numcol;bool cover;}tt[N*4];int len,numcolour,numop,x,y;void build_tree(int lp,int rp,int pos){tt[pos].left=lp;tt[pos].right=rp;tt[pos].numcol=(1<<1);tt[pos].cover=true;if(lp==rp)return;int mid=(lp+rp)/2;build_tree(lp,mid,pos*2);build_tree(mid+1,rp,pos*2+1);}void add(int lp,int rp,int id,int pos){if(lp<=tt[pos].left&&rp>=tt[pos].right){tt[pos].cover=true;tt[pos].numcol=(1<<id);return;}if(tt[pos].cover){tt[pos*2].cover=true;tt[pos*2+1].cover=true;tt[pos*2].numcol=tt[pos].numcol;tt[pos*2+1].numcol=tt[pos].numcol;tt[pos].cover=false;}int mid=(tt[pos].left+tt[pos].right)/2;if(lp<=mid)add(lp,rp,id,pos*2);if(rp>mid)add(lp,rp,id,pos*2+1);tt[pos].numcol=tt[pos*2].numcol|tt[pos*2+1].numcol;}int query(int lp,int rp,int pos){if(tt[pos].left==lp&&tt[pos].right==rp){return tt[pos].numcol;}if(tt[pos].cover){tt[2*pos].cover=true;tt[2*pos+1].cover=true;tt[2*pos].numcol=tt[pos].numcol;tt[2*pos+1].numcol=tt[pos].numcol;tt[pos].cover=false;}int mid=(tt[pos].left+tt[pos].right)/2;if(lp>mid)return query(lp,rp,pos*2+1);else if(rp<=mid)return query(lp,rp,pos*2);elsereturn query(lp,mid,pos*2)|query(mid+1,rp,pos*2+1);}int fenjie(int x){int ans=0;while(x){  if(x%2)  ans++;  x/=2;}return ans;}int main(){//freopen("1.txt","r",stdin);while(~scanf("%d%d%d",&len,&numcolour,&numop)){  build_tree(1,len,1);  char ss[2];  int id;  while(numop--){    scanf("%s",ss);if(ss[0]=='C'){  scanf("%d%d%d",&x,&y,&id);  if(x>y)  swap(x,y);  add(x,y,id,1);}else{  scanf("%d%d",&x,&y);  if(x>y)  swap(x,y);  int sum=query(x,y,1);  int total=fenjie(sum);  printf("%d\n",total);}  }}return 0;}