hdu 3397 Sequence operation (线段树 区间合并 多重标记)

时间:2023-03-08 21:04:21

链接;http://acm.hdu.edu.cn/showproblem.php?pid=3397

题意:

给你一串01串,有5种操作

0. 区间全部变为0

1.区间全部变为1

2.区间异或

3.询问区间1的个数

4.询问区间被最长连续1的长度

思路:

这5个操作都是比较基础的线段树操作,难点在于有两种修改操作,这类题之前也写过,之前是乘法和加法,这个是区间亦或和区间更新值,但是思路是可以借鉴的,我们要推出这两个操作的关系,这样才能维护好这两个标记,我们用两个标记:same , rev ,分别表示区间更新值和区间异或,那么向下更新的时候如果如果有same标记,清空当前区间的rev标记,简单维护下就好了,如果有rev标记,且有same标记,那么直接对same异或维护,如果没有same标记那么就维护下区间异或就好了。

写的超爽,一遍就a了,美滋滋,还以为又要找好久的错。。

实现代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define mid int m = (l + r) >> 1
#define ll long long const int M = 1e5 + ;
int lsum1[M<<],rsum1[M<<],sum1[M<<];
int lsum0[M<<],rsum0[M<<],sum0[M<<];
int sum[M<<],same[M<<],rev[M<<];
int a[M]; void pushup(int l,int r,int rt){
mid;
sum[rt] = sum[rt<<] + sum[rt<<|];
lsum0[rt] = lsum0[rt<<]; lsum1[rt] = lsum1[rt<<];
rsum0[rt] = rsum0[rt<<|]; rsum1[rt] = rsum1[rt<<|];
if(lsum0[rt] == m-l+) lsum0[rt] += lsum0[rt<<|];
if(rsum0[rt] == r-m) rsum0[rt] += rsum0[rt<<];
if(lsum1[rt] == m-l+) lsum1[rt] += lsum1[rt<<|];
if(rsum1[rt] == r-m) rsum1[rt] += rsum1[rt<<];
sum0[rt] = max(max(sum0[rt<<],sum0[rt<<|]),lsum0[rt<<|]+rsum0[rt<<]);
sum1[rt] = max(max(sum1[rt<<],sum1[rt<<|]),lsum1[rt<<|]+rsum1[rt<<]);
} void swa(int len,int rt){
sum[rt] = len - sum[rt];
swap(lsum1[rt],lsum0[rt]);
swap(rsum1[rt],rsum0[rt]);
swap(sum1[rt],sum0[rt]);
} void pushdown(int l,int r,int rt){
mid;
if(same[rt]!=-){
rev[rt<<] = rev[rt<<|] = ;
same[rt<<] = same[rt<<|] = same[rt];
if(same[rt]){
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = m-l+;
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = r-m;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = ;
}
else{
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = ;
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = ;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = m-l+;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = r-m;
}
same[rt] = -;
}
if(rev[rt]){
if(same[rt<<] != -){
same[rt<<] ^= ;
if(same[rt<<]){
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = m-l+;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = ;
}
else{
sum[rt<<] = lsum1[rt<<] = rsum1[rt<<] = sum1[rt<<] = ;
lsum0[rt<<] = rsum0[rt<<] = sum0[rt<<] = m-l+;
}
}
else{
rev[rt<<] ^= ;
swa(m-l+,rt<<);
}
if(same[rt<<|] != -){
same[rt<<|] ^= ;
if(same[rt<<|]){
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = r-m;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = ;
}
else{
sum[rt<<|] = lsum1[rt<<|] = rsum1[rt<<|] = sum1[rt<<|] = ;
sum0[rt<<|] = rsum0[rt<<|] = lsum0[rt<<|] = r-m;
}
}
else{
rev[rt<<|] ^= ;
swa(r-m,rt<<|);
}
rev[rt] = ;
}
} void build(int l,int r,int rt){
same[rt] = -; rev[rt] = ;
lsum1[rt] = rsum1[rt] = lsum0[rt] = rsum0[rt] = sum0[rt] = sum1[rt] = sum[rt] = ;
if(l == r){
if(a[l]){
lsum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else {
sum1[rt] = sum[rt] = sum1[rt] = rsum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
return ;
}
mid ;
build(lson); build(rson);
pushup(l,r,rt);
} void update_same(int L,int R,int c,int l,int r,int rt){
if(L <= l&&R >= r){
rev[rt] = ;
same[rt] = c;
if(same[rt]){
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else{
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+;
}
return ;
}
pushdown(l,r,rt);
mid;
if(L <= m) update_same(L,R,c,lson);
if(R > m) update_same(L,R,c,rson);
pushup(l,r,rt);
} void update_rev(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
if(same[rt] != -){
same[rt] ^= ;
if(same[rt]){
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = r-l+;
lsum0[rt] = rsum0[rt] = sum0[rt] = ;
}
else{
sum[rt] = lsum1[rt] = rsum1[rt] = sum1[rt] = ;
lsum0[rt] = rsum0[rt] = sum0[rt] = r-l+;
}
}
else{
rev[rt] ^= ;
swa(r-l+,rt);
}
return ;
}
mid ;
pushdown(l,r,rt);
if(L <= m) update_rev(L,R,lson);
if(R > m) update_rev(L,R,rson);
pushup(l,r,rt);
} int query_sum(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum[rt];
}
pushdown(l,r,rt);
mid;
int ret = ;
if(L <= m) ret += query_sum(L,R,lson);
if(R > m) ret += query_sum(L,R,rson);
return ret;
} int query_max(int L,int R,int l,int r,int rt){
if(L <= l&&R >= r){
return sum1[rt];
}
pushdown(l,r,rt);
mid;
int ret = ;
if(L > m) return query_max(L,R,rson);
if(R <= m) return query_max(L,R,lson);
int t1 = query_max(L,R,lson);
int t2 = query_max(L,R,rson);
int ls = min(rsum1[rt<<],m-L+);
int rs = min(lsum1[rt<<|],R-m);
return max(max(t1,t2),ls+rs);
} int main()
{
int n,q,x,y,op,t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&q);
for(int i = ;i <= n;i ++)
scanf("%d",&a[i]);
build(,n,);
while(q--){
scanf("%d%d%d",&op,&x,&y);
x++; y++;
if(op == ){
update_same(x,y,,,n,);
}
else if(op == ){
update_same(x,y,,,n,);
}
else if(op == ){
update_rev(x,y,,n,);
}
else if(op == ){
printf("%d\n",query_sum(x,y,,n,));
}
else {
printf("%d\n",query_max(x,y,,n,));
}
}
}
return ;
}