poj2777Count Color(线段树 成段更新)
http://poj.org/problem?id=2777
网上的一段解释
经典的线段树题目。成段更新,在利用一个数组在查询顺次整段区间时,登记未曾被遮蔽到的颜色,并对其所对应的编号符号为1.而在成段更新结点时,若某区间将揭示混杂色,就让其子节点更新为它的颜色,并符号该结点。总之,对于成段更新区间属性的题目等闲用线段树来处理,利用时要保留结点属性的单一性,但更新摧毁了这种单一性时,则应递归地坚持该结点孩子的属性的单一性。只有这么,在更新垄断才不至于退化到O(n)的混杂度,保证高效率。
View Code
1 #include <iostream> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include<string.h> 5 using namespace std; 6 int s[300010]; 7 int x,co[32]; 8 void ctree(int l,int r,int w) 9 { 10 if(l==r) 11 { 12 s[w] = 1; 13 return ; 14 } 15 int m = (l+r)/2; 16 ctree(l,m,2*w); 17 ctree(m+1,r,2*w+1); 18 } 19 void add(int a,int b,int l,int r,int w) 20 { 21 if(l==a&&b==r) 22 { 23 s[w] = x; 24 } 25 else 26 { 27 int m = (l+r)/2; 28 if(s[w]>0) 29 { 30 s[2*w] = s[w]; 31 s[2*w+1] = s[w]; 32 s[w] = -1; 33 } 34 if(b<=m) 35 add(a,b,l,m,2*w); 36 else 37 if(a>m) 38 add(a,b,m+1,r,2*w+1); 39 else 40 { 41 add(a,m,l,m,2*w); 42 add(m+1,b,m+1,r,2*w+1); 43 } 44 } 45 } 46 void search(int a,int b,int l,int r,int w) 47 { 48 if(s[w]>0) 49 co[s[w]] = 1; 50 else 51 { 52 int m = (l+r)/2; 53 if(b<=m) 54 search(a,b,l,m,2*w); 55 else 56 if(a>m) 57 search(a,b,m+1,r,2*w+1); 58 else 59 { 60 search(a,m,l,m,2*w); 61 search(m+1,b,m+1,r,2*w+1); 62 } 63 } 64 } 65 int main() 66 { 67 int a,b,i,j,t,l,o,m,h,num; 68 char c[10]; 69 scanf("%d%d%d", &l,&t,&o); 70 ctree(1,l,1); 71 s[1] = 1; 72 while(o--) 73 { 74 scanf("%s",&c); 75 if(c[0] == 'P') 76 { 77 scanf("%d%d", &a,&b); 78 if(a>b) 79 { 80 h = a; 81 a = b; 82 b = h; 83 } 84 num = 0; 85 memset(co,0,sizeof(co)); 86 search(a,b,1,l,1); 87 for(i = 1; i <= t ; i++) 88 { 89 if(co[i]) 90 num++; 91 //printf("%d]",co[i]); 92 } 93 printf("%d\n",num); 94 } 95 else 96 { 97 scanf("%d%d%d",&a,&b,&x); 98 add(a,b,1,l,1); 99 } 100 } 101 return 0; 102 }
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include<stdlib.h> 5 #include<iostream> 6 using namespace std; 7 #define N 100010 8 int s[N<<2],n,t,m,co[31]; 9 void build(int l,int r,int w) 10 { 11 if(l==r) 12 { 13 s[w] = 1; 14 return ; 15 } 16 int m = (l+r)>>1; 17 build(l,m,w<<1); 18 build(m+1,r,w<<1|1); 19 } 20 void add(int a,int b,int d,int l,int r,int w) 21 { 22 if(a<=l&&b>=r) 23 { 24 s[w] = d; 25 return ; 26 } 27 if(s[w]>0) 28 { 29 s[w<<1] = s[w]; 30 s[w<<1|1] = s[w]; 31 s[w] = -1; 32 } 33 int m = (l+r)>>1; 34 if(a<=m) add(a,b,d,l,m,w<<1); 35 if(b>m) add(a,b,d,m+1,r,w<<1|1); 36 } 37 void query(int a,int b,int l,int r,int w) 38 { 39 if(s[w]>0) 40 { 41 co[s[w]] = 1; 42 return ; 43 } 44 int m = (l+r)>>1; 45 if(a<=m) query(a,b,l,m,w<<1); 46 if(b>m) query(a,b,m+1,r,w<<1|1); 47 } 48 int main() 49 { 50 int i,a,b,d,num; 51 char c[10]; 52 while(cin>>n>>t>>m) 53 { 54 build(1,n,1); 55 s[1] = 1; 56 while(m--) 57 { 58 scanf("%s",&c); 59 if(c[0]=='C') 60 { 61 scanf("%d%d%d",&a,&b,&d); 62 int y = max(a,b); 63 int x = min(a,b); 64 add(x,y,d,1,n,1); 65 } 66 else 67 { 68 scanf("%d%d",&a,&b); 69 int y = max(a,b); 70 int x = min(a,b); 71 num=0; 72 memset(co,0,sizeof(co)); 73 query(x,y,1,n,1); 74 for(i = 1; i <= t ; i++) 75 if(co[i]) num++; 76 printf("%d\n",num); 77 } 78 } 79 } 80 }