poj 2777(线段树+lazy思想) 小小粉刷匠

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
",sum);
68             }
69         }
70     }
71     return 0;
72 }
原文地址:https://www.cnblogs.com/JJCHEHEDA/p/4724775.html