有5个操作,
0 区间全部置为0
1 区间全部置为1
2 区间的值取反,1 变0 ,0变1,
3 求区间1 的个数。
4 求区间连续最长的1.
思路:
lazy标记, 有 -1,0,1,2, 四种标记,
-1 是什么都没有,
0,1 算是一种操作,区间修改,
2 是一种操作,亦或。
因为亦或这个操作。我们存一下1 的所有数据,0的所有数据,便于以后交换。
我们要考虑一下优先级的问题,
1,无论当前节点之前是什么标记,现在给它 0,或者1 的标记,那就直接覆盖就好。
2,当前节点之前是0 或 1 标记,现在给他 2 标记,那么我们就把之前的标记亦或一下,
3,当前节点之前是 2 或者 -1,我们这个时候就要交换0 的数据和1 的数据,
然后lazy标记,之前为-1现在为2,之前为2现在为-1,因为两次亦或相当于不变。
#include <bits/stdc++.h>
#define mem(x,v) memset(x,v,sizeof(x))
#define rep(i,a,b) for (int i = a; i < b; i++)
#define per(i,a,b) for (int i = a; i > b; i--)
using namespace std;
typedef long long LL;
const double EPS = 1e-10;
const int INF = 0x3f3f3f3f;
const int N = 1e5+100;
struct segtree{
int l,r,a,b;
int w,ll1,rr1,ll,ll0,rr0,rr; // w 是区间和,ll1,ll0 从左1 或 0 的个数,rr1,rr0 从右的个数,ll,rr,区间最长1 或者 0 的个数。
int lazy; // lazy标记,0,1,2,-1,四种标记。
int calc_mid(){
return (a + b)/2;
}
int calc_len(){
return (b - a);
}
void calc_swap(){ //交换。
swap(ll1,ll0);
swap(rr1,rr0);
swap(ll,rr);
return;
}
}f[N*2];
int n,c[N],t,m;
void push_up(int p){
f[p].w = f[f[p].l].w + f[f[p].r].w;
f[p].ll1 = f[f[p].l].ll1; if (f[f[p].l].ll1 == f[f[p].l].calc_len()) f[p].ll1 += f[f[p].r].ll1;
f[p].rr1 = f[f[p].r].rr1; if (f[f[p].r].rr1 == f[f[p].r].calc_len()) f[p].rr1 += f[f[p].l].rr1;
f[p].ll = max(f[f[p].l].ll,max(f[f[p].r].ll,f[f[p].l].rr1+f[f[p].r].ll1));
f[p].ll0 = f[f[p].l].ll0; if (f[f[p].l].ll0 == f[f[p].l].calc_len()) f[p].ll0 +=