HDU 4391 Paint The Wall

线段树

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 
  6 #define lson l, m, rt << 1
  7 #define rson m + 1, r, rt << 1 | 1
  8 
  9 using namespace std;
 10 
 11 const int MAXN = 100010;
 12 
 13 int N, Q;
 14 int color[ MAXN << 2 ]; //记录该区间的颜色
 15 int flag[ MAXN << 2 ];  //记录该区间是否是相同颜色
 16 int maxi[ MAXN << 2 ];  //记录区间最值,用于优化查询
 17 int mini[ MAXN << 2 ];
 18 
 19 void PushUp( int rt )
 20 {
 21     int lc = rt << 1;
 22     int rc = rt << 1 | 1;
 23 
 24     if ( flag[lc] && flag[rc] && color[lc] == color[rc] )
 25     {
 26         flag[rt] = 1;
 27         color[rt] = color[lc];
 28     }
 29     else
 30     {
 31         flag[rt] = 0;
 32         color[rt] = -1;
 33     }
 34 
 35     maxi[rt] = max( maxi[lc], maxi[rc] );
 36     mini[rt] = min( mini[lc], mini[rc] );
 37     return;
 38 }
 39 
 40 void PushDown( int rt )
 41 {
 42     int lc = rt << 1;
 43     int rc = rt << 1 | 1;
 44     if ( flag[rt] )
 45     {
 46         flag[lc] = flag[rc] = flag[rt];
 47         color[lc] = color[rc] = color[rt];
 48         maxi[lc] = maxi[rc] = color[rt];
 49         mini[lc] = mini[rc] = color[rt];
 50         flag[rt] = 0;
 51     }
 52     return;
 53 }
 54 
 55 void build( int l, int r, int rt )
 56 {
 57     flag[rt] = 0;
 58     if ( l == r )
 59     {
 60         scanf( "%d", &color[rt] );
 61         flag[rt] = 1;
 62         maxi[rt] = mini[rt] = color[rt];
 63         return;
 64     }
 65     int m = ( l + r ) >> 1;
 66     build( lson );
 67     build( rson );
 68     PushUp( rt );
 69     return;
 70 }
 71 
 72 void Update( int L, int R, int z, int l, int r, int rt )
 73 {
 74     if ( L <= l && r <= R )
 75     {
 76         flag[rt] = 1;
 77         color[rt] = z;
 78         maxi[rt] = z;
 79         mini[rt] = z;
 80         return;
 81     }
 82     PushDown( rt );
 83 
 84     int m = ( l + r ) >> 1;
 85     if ( L <= m ) Update( L, R, z, lson );
 86     if ( R > m ) Update( L, R, z, rson );
 87 
 88     PushUp(rt);
 89 
 90     return;
 91 }
 92 
 93 int Query( int L, int R, int z, int l, int r, int rt )
 94 {
 95     if ( L <= l && r <= R )
 96     {
 97         if ( flag[rt] && color[rt] == z ) return r - l + 1;
 98         else if ( z < mini[rt] || z > maxi[rt] ) return 0;
 99     }
100     PushDown(rt);
101 
102     int m = ( l + r ) >> 1;
103     int ans = 0;
104     if ( L <= m ) ans += Query( L, R, z, lson );
105     if ( R > m ) ans += Query( L, R, z, rson );
106 
107     PushUp(rt);
108     return ans;
109 }
110 
111 int main()
112 {
113     while ( ~scanf( "%d%d", &N, &Q ) )
114     {
115         build( 0, N - 1, 1 );
116         while ( Q-- )
117         {
118             int a, l, r, z;
119             scanf( "%d%d%d%d", &a, &l, &r, &z );
120             if ( a == 1 ) Update( l, r, z, 0, N - 1, 1 );
121             else printf("%d\n", Query( l, r, z, 0, N - 1, 1 ) );
122         }
123     }
124     return 0;
125 }

 

转载于:https://www.cnblogs.com/GBRgbr/archive/2013/05/06/3063874.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值