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 }
View Code

 

posted @ 2012-07-27 21:48  _雨  阅读(193)  评论(0编辑  收藏  举报