hdu - 5023 - A Corrupt Mayor's Performance Art(线段树)

题目原文废话太多太多太多,我就不copyandpaste到这里啦。。发个链接吧题目

题目意思就是:P  l  r  c  将区间 [l ,r]上的颜色变成c    Q  l r 就是打印出区间[l,r]中所有的颜色,并且要升序排列出来,注意最坑的就是各个区间的颜色初始化为2,这个条件竟然夹杂在那又长又臭的题目的某个角落里面!!

比赛的时候思路是有的,并且也能想到用set来撸,哎,对set的用法太挫逼了,写线段树又写得太挫逼了,后来补回这道题的时候,才发现其实是一道非常常规的线段树,所以最近给自己留了20道线段树慢慢刷,主要是能够更加熟练地写出线段树的模板,因为我发觉之前只是看得懂别人写的线段树的代码,却很少完全靠自己去敲出来,今天在补这道题的时候依然wa了很多次,最终才发现在query的那里忘记PushDown了  QAQ,废话少说 直接贴代码:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <queue>
 4 #include <set>
 5 #include <cstring>
 6 using namespace std;
 7 #define lson l,m,rt<<1
 8 #define rson m+1,r,rt<<1|1
 9 const int maxn = 1001111;
10 set<int> ans;
11 int SIZE;
12 int sum[maxn<<2];
13 void PushDown(int rt){
14     if(sum[rt]){
15         sum[rt<<1] = sum[rt];
16         sum[rt<<1|1] = sum[rt];
17         sum[rt] = 0;
18     }
19 }
20 void build(int l,int r,int rt){
21     if(l == r){
22         sum[rt] = 2;return;
23     }
24     int m = (l + r) >>1;
25     build(lson);
26     build(rson);
27     return ;
28 }
29 void update(int L,int R,int c,int l,int r,int rt){
30     if(L <= l&&r <= R){
31         sum[rt] = c;
32         return ;
33     }
34     int m = (l + r)>>1;
35     PushDown(rt);
36     if(L <= m) update(L,R,c,lson);
37 
38     if(m <  R) update(L,R,c,rson);
39     return ;
40 }
41 void query(int L,int R,int l,int r,int rt){
42     //if(rt > SIZE) return;
43     if(L <= l&&r <= R&&sum[rt]){
44         ans.insert(sum[rt]);
45         return ;
46     }
47     PushDown(rt);
48     int m = (l + r)>>1;
49     if(L <= m) query( L, R,lson);
50     if(m <  R) query( L, R,rson);
51     return;
52 }
53 void print(){
54     set<int>::iterator it;
55     it = ans.begin();
56     cout<<*it;
57     ans.erase(it);
58     for(it = ans.begin();it != ans.end();++it)
59         printf(" %d",*it);
60         puts("");
61 }
62 void print_debug(){
63     cout<<"sum: "<<endl;
64     for(int i = 1;i <= 20;i++)
65         cout<<sum[i]<<" ";
66         puts("");
67 }
68 int main(){
69     int N,Q,a,b,c;
70     char ope[3];
71     while(~scanf("%d%d",&N,&Q)&&(N+Q)){
72         SIZE = (N+1)*N/2;
73         memset(sum,0,sizeof(sum));
74         build(1,N,1);
75         while(Q--){
76             scanf("%s",ope);
77             if(ope[0] == 'Q'){
78                 scanf("%d%d",&a,&b);
79                 ans.clear();
80                 query(a,b,1,N,1);
81                 print();
82             }else{
83                 scanf("%d%d%d",&a,&b,&c);
84                 update(a,b,c,1,N,1);
85                 //print_debug();
86             }
87         }
88     }
89     return 0;
90 }
View Code

然后我又看到了另一份比较好玩的代码,是通过巧妙的位移运算来表示的,恩 感觉挺好的   链接请点击~

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 using namespace std;
  5 
  6 #define lson l , mid , rt << 1
  7 #define rson mid + 1 , r , rt << 1 | 1
  8 #define LL int
  9 
 10 const int maxn = 1100017;
 11 LL add[maxn<<2];
 12 LL sum[maxn<<2];
 13 void PushUp(int rt)
 14 {
 15     //把当前结点的信息更新到父结点
 16     sum[rt] = sum[rt<<1] | sum[rt<<1|1];//总共的颜色
 17 }
 18 void PushDown(int rt,int m)
 19 {
 20     if(add[rt])
 21     {
 22         add[rt<<1] = add[rt];
 23         add[rt<<1|1] = add[rt];
 24         sum[rt<<1] = add[rt] ;
 25         sum[rt<<1|1] = add[rt] ;
 26         add[rt] = 0;//将标记向儿子节点移动后,父节点的延迟标记去掉
 27         //传递后,当前节点标记域清空
 28     }
 29 }
 30 void build(int l,int r,int rt)
 31 {
 32     add[rt] = 0;//初始化为所有结点未被标记
 33     if (l == r)
 34     {
 35         sum[rt]=2;//初始颜色为2
 36         return ;
 37     }
 38     int mid = (l + r) >> 1;
 39     build(lson);
 40     build(rson);
 41     PushUp(rt);
 42 }
 43 void update(int L,int R,int c,int l,int r,int rt)
 44 {
 45     if (L <= l && r <= R)
 46     {
 47         add[rt] =1<<(c-1);//位运算左移表示有某种颜色
 48         sum[rt] =1<<(c-1);
 49         return ;
 50     }
 51     PushDown(rt , r - l + 1);//----延迟标志域向下传递
 52     int mid = (l + r) >> 1;
 53     if (L <= mid)
 54         update(L , R , c , lson);//更新左儿子
 55     if (mid < R)
 56         update(L , R , c , rson);//更新右儿子
 57     PushUp(rt);
 58 }
 59 LL query(int L,int R,int l,int r,int rt)
 60 {
 61     if (L <= l && r <= R)
 62     {
 63         return sum[rt];
 64     }
 65     //要取rt子节点的值时,也要先把rt的延迟标记向下移动
 66     PushDown(rt , r - l + 1);
 67     int mid = (l + r) >> 1;
 68     LL ret = 0;
 69     if (L <= mid)
 70         ret |= query(L , R , lson);
 71     if (mid < R)
 72         ret |= query(L , R , rson);
 73     return ret;
 74 }
 75 int main()
 76 {
 77     int N , Q;
 78     int a , b , c;
 79     while(scanf("%d%d",&N,&Q))
 80     {
 81         if(N==0 && Q==0)
 82             break;
 83         build(1 , N , 1);//建树
 84         while(Q--)//Q为询问次数
 85         {
 86             char op[2];
 87             scanf("%s",op);
 88             if(op[0] == 'Q')//Q为询问次数
 89             {
 90                 scanf("%d%d",&a,&b);
 91                 LL tt=query(a , b , 1 , N , 1);
 92                 LL flag = 0;
 93                 for(int i=1; i<=30; i++)
 94                 {
 95                     if(tt>>(i-1)&1 && flag==0)
 96                     {
 97                         printf("%d",i);
 98                         flag = 1;
 99                     }
100                     else if(tt>>(i-1)&1)
101                         printf(" %d",i);
102                 }
103                 printf("\n");
104             }
105             else
106             {
107                 scanf("%d%d%d",&a,&b,&c);
108                 update(a , b , c , 1 , N , 1);
109             }
110         }
111     }
112     return 0;
113 }
View Code

 

posted @ 2014-09-25 16:13  jusonalien  阅读(248)  评论(0编辑  收藏  举报