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 }

 

你可能感兴趣的:(sequence)