http://poj.org/problem?id=2777
题目大意 涂颜色,输入长度,颜色总数,涂颜色次数,初始颜色都为1,然后当输入为C的时候将x到y涂为颜色z,输入为Q的时候输出x到y的颜色总数
很明显的区间线段树,然后加lazy思想记录
lazy操作为了避免查找到每一个子节点区间而费时,将查找到的区间作标记,但查找到这个区间或还要继续像下查找的时候
将此区间的数据传给下面两个区间树
因为这题颜色总类只有30种很少,所以偷了个懒,将判断与记录操作合并到一个结构体上了,然后用类似hash的数组记录颜色总数
code
1 #include<cstdio> 2 #include<string.h> 3 using namespace std; 4 struct point 5 { 6 int l,r; 7 int color; 8 }; 9 point tree[100000*4]; 10 int visit[31]; 11 void build(int i,int left,int right) 12 { 13 tree[i].l=left;tree[i].r=right; 14 tree[i].color=1; 15 if(left==right)return; 16 int mid=(left+right)/2; 17 build(i*2,left,mid); 18 build(i*2+1,mid+1,right); 19 } 20 void update(int i,int left,int right,int val) 21 { 22 if (left<=tree[i].l&&tree[i].r<=right){tree[i].color=val;return ;} 23 if (tree[i].color!=-1) //lazy操作 24 { 25 tree[i*2].color=tree[i*2+1].color=tree[i].color; 26 tree[i].color=-1; 27 } 28 if (left<=tree[i*2].r) update(i*2,left,right,val); 29 if (right>=tree[i*2+1].l) update(i*2+1,left,right,val); 30 } 31 void find(int i,int left,int right) 32 { 33 if (tree[i].color!=-1) {visit[tree[i].color]=1;return ;} 34 if (tree[i].l==tree[i].r) return; 35 if (tree[i].color!=-1) 36 { 37 tree[i*2].color=tree[i*2+1].color=tree[i].color; 38 tree[i].color=-1; 39 } 40 if (left<=tree[i*2].r) find(i*2,left,right); 41 if (right>=tree[i*2+1].l) find(i*2+1,left,right); 42 } 43 int main() 44 { 45 int x,y,z,n,m,k; 46 char op; 47 while (~scanf("%d %d %d",&x,&y,&z)) 48 { 49 build(1,1,x); 50 while (z--) 51 { 52 scanf(" %c",&op); 53 if (op=='C') 54 { 55 scanf("%d %d %d",&n,&m,&k); 56 update(1,n,m,k); 57 } 58 else 59 { 60 scanf("%d %d",&n,&m); 61 memset(visit,0,sizeof(visit)); 62 find(1,n,m); 63 int sum=0; 64 for (int i=1;i<=30;i++) 65 if (visit[i]==1) 66 sum++; 67 printf("%d\n",sum); 68 } 69 } 70 } 71 return 0; 72 }