HDU 3397 Sequence operation

裸线段树区间合并,题目本身不难,就是细节处理比较麻烦。

因为涉及到异或运算,所以连续0和连续1的个数都要记录一下。

操作的懒惰标记我只用了一个flag,注意flag更新时的细节,我分了三种情况:

flag == -1 或者 当前操作为0或1:更新时直接赋值。因为0, 1操作都可以直接覆盖前面的操作。

flag == 0或1,当前操作为2(xor):flag ^= 1。前面标记过0或1,当前操作为异或,那么改变flag标记

flag == 2,当前操作为2(xor): flag = -1。前面只出现过异或运算,没出现过0,1运算。因为异或两次相当于没异或,所以清除标记即可。

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <cstdlib>
  4 #include <algorithm>
  5 
  6 using namespace std;
  7 
  8 #define lson l, m, rt << 1
  9 #define rson m + 1, r, rt << 1 | 1
 10 
 11 const int MAXN = 100010;
 12 
 13 int N, Q, maxLen;
 14 int cnt[ MAXN << 2 ];     // 1 的个数
 15 int len[ MAXN << 2 ];     //最长连续1长度
 16 int len0[ MAXN << 2 ];     //最长连续0长度
 17 int flag[ MAXN << 2 ];    //懒惰标记
 18 int Llen[ MAXN << 2 ];    //左端连续1长度
 19 int Llen0[ MAXN << 2 ];    //左端连续0长度
 20 int Rlen[ MAXN << 2 ];    //右端连续1长度
 21 int Rlen0[ MAXN << 2 ];    //右端连续0长度
 22 bool Lnode[ MAXN << 2 ];  //左端点是否为1
 23 bool Rnode[ MAXN << 2 ];  //右端点是否为1
 24 
 25 void PushUp( int rt, int l, int r, int m )
 26 {
 27     int lc = rt << 1;
 28     int rc = rt << 1 | 1;
 29 
 30     cnt[rt] = cnt[lc] + cnt[rc];
 31 
 32     Lnode[rt] = Lnode[lc];
 33     Rnode[rt] = Rnode[rc];
 34 
 35     Llen[rt] = Llen[lc];
 36     Rlen[rt] = Rlen[rc];
 37 
 38     Llen0[rt] = Llen0[lc];
 39     Rlen0[rt] = Rlen0[rc];
 40 
 41     if ( Llen[lc] == m - l + 1 ) Llen[rt] += Llen[rc];
 42     if ( Llen0[lc] == m - l + 1 ) Llen0[rt] += Llen0[rc];
 43 
 44     if ( Rlen[rc] == r - m )     Rlen[rt] += Rlen[lc];
 45     if ( Rlen0[rc] == r - m )     Rlen0[rt] += Rlen0[lc];
 46 
 47     len[rt] = max( len[lc], len[rc] );
 48     len0[rt] = max( len0[lc], len0[rc] );
 49     if ( Rnode[lc] && Lnode[rc] )
 50     {
 51         len[rt] = max( len[rt], Rlen[lc] + Llen[rc] );
 52     }
 53 
 54     if ( !Rnode[lc] && !Lnode[rc] )
 55     {
 56         len0[rt] = max( len0[rt], Rlen0[lc] + Llen0[rc] );
 57     }
 58 
 59     return;
 60 }
 61 
 62 void chuli( int op, int rt, int l, int r )
 63 {
 64     if ( op == 0 )
 65     {
 66         cnt[rt] = 0;
 67         Lnode[rt] = Rnode[rt] = false;
 68         len[rt] = Llen[rt] = Rlen[rt] = 0;
 69         len0[rt] = Llen0[rt] = Rlen0[rt] = r - l + 1;
 70     }
 71     else if ( op == 1 )
 72     {
 73         cnt[rt] = r - l + 1;
 74         Lnode[rt] = Rnode[rt] = true;
 75         len[rt] = Llen[rt] = Rlen[rt] = r - l + 1;
 76         len0[rt] = Llen0[rt] = Rlen0[rt] = 0;
 77     }
 78     else
 79     {
 80         cnt[rt] = r - l + 1 - cnt[rt];
 81         Lnode[rt] = !Lnode[rt];
 82         Rnode[rt] = !Rnode[rt];
 83         swap( Llen[rt], Llen0[rt] );
 84         swap( Rlen[rt], Rlen0[rt] );
 85         swap( len[rt], len0[rt] );
 86     }
 87     return;
 88 }
 89 
 90 void fuzhi( int rt, int c, int l, int r )
 91 {
 92     if ( flag[rt] == -1 )
 93     {
 94         flag[rt] = c;
 95         return;
 96     }
 97     if ( c == 2 )
 98     {
 99         if ( flag[rt] == 0 || flag[rt] == 1 ) flag[rt] ^= 1;
100         else if ( flag[rt] == 2 ) flag[rt] = -1;
101     }
102     else flag[rt] = c;
103 
104     return;
105 }
106 
107 void PushDown( int rt, int l, int r, int m )
108 {
109     int lc = rt << 1;
110     int rc = rt << 1 | 1;
111     if ( flag[rt] != -1 )
112     {
113         if ( flag[rt] == 0 || flag[rt] == 1 ) flag[lc] = flag[rc] = flag[rt];
114         else
115         {
116             fuzhi( lc, flag[rt], l, m );
117             fuzhi( rc, flag[rt], m + 1, r );
118         }
119         chuli( flag[lc], lc, l, m );
120         chuli( flag[rc], rc, m + 1, r );
121         flag[rt] = -1;
122     }
123     return;
124 }
125 
126 void Build( int l, int r, int rt )
127 {
128     flag[rt] = -1;
129     if ( l == r )
130     {
131         int num;
132         scanf( "%d", &num );
133         if ( num == 1 )
134         {
135             cnt[rt] = 1;
136             Llen[rt] = Rlen[rt] = len[rt] = 1;
137             Llen0[rt] = Rlen0[rt] = len0[rt] = 0;
138             Lnode[rt] = Rnode[rt] = true;
139         }
140         else
141         {
142             cnt[rt] = 0;
143             Llen[rt] = Rlen[rt] = len[rt] = 0;
144             Llen0[rt] = Rlen0[rt] = len0[rt] = 1;
145             Lnode[rt] = Rnode[rt] = false;
146         }
147         return;
148     }
149 
150     int m = ( l + r ) >> 1;
151     Build( lson );
152     Build( rson );
153     PushUp( rt, l, r, m );
154 
155     return;
156 }
157 
158 void Update( int L ,int R, int c, int l, int r, int rt )
159 {
160     int m = ( l + r ) >> 1;
161 
162     if ( L <= l && r <= R )
163     {
164         fuzhi( rt, c, l, r );
165         chuli( flag[rt], rt, l, r );
166         return;
167     }
168 
169     PushDown( rt, l, r, m );
170 
171     if ( L <= m ) Update( L, R, c, lson );
172     if ( R > m )  Update( L, R, c, rson );
173     PushUp( rt, l, r, m );
174 
175     return;
176 }
177 
178 int Query( int L, int R, int l, int r, int rt )
179 {
180 
181     int m = ( l + r ) >> 1;
182     if ( L <= l && r <= R )
183     {
184         maxLen = max( maxLen, len[rt] );
185         return cnt[rt];
186     }
187 
188     PushDown( rt, l, r, m );
189 
190     int ret = 0;
191     if ( L <= m ) ret += Query( L, R, lson );
192     if ( R > m )  ret += Query( L, R, rson );
193 
194     PushUp( rt, l, r, m );
195 
196     if ( Lnode[rt << 1 | 1] && Rnode[rt << 1] )
197         maxLen = max( maxLen, min( Llen[rt << 1 | 1], R - m ) + min( Rlen[ rt << 1 ], m - L + 1 ) );
198 
199 
200     return ret;
201 }
202 
203 int main()
204 {
205     //freopen( "in2.txt", "r", stdin );
206     //freopen( "out.txt", "w", stdout );
207     int T;
208     scanf( "%d", &T );
209     while ( T-- )
210     {
211         scanf( "%d%d", &N, &Q );
212         Build( 0, N - 1, 1 );
213         while ( Q-- )
214         {
215             int op, a, b;
216             scanf( "%d%d%d", &op, &a, &b );
217             {
218                 if ( op < 3 )
219                     Update(a, b, op, 0, N - 1, 1 );
220                 else
221                 {
222                     maxLen = 0;
223                     int ans = Query( a, b, 0, N - 1, 1 );
224                     if ( op == 3 ) printf( "%d\n", ans );
225                     else printf( "%d\n", maxLen );
226                 }
227             }
228         }
229     }
230     return 0;
231 }
原文地址:https://www.cnblogs.com/GBRgbr/p/3089504.html