链接:F. Flip
题意:
给出一个01串,有两种操作:
思路:
线段树维护区间左右端点分别是什么,该区间的合法子区间的数量,以左右端点为起点的最长合法区间的长度。区间合并的时候如果两个端点不同可以增加贡献。注意查询的时候用类似于pushup的操作,没找到一个小区间合并到答案里。
代码:
#include
using namespace std;
#define ll long long
const int maxn = 1e6 + 7;
int x[maxn] , n , m , y[maxn];
struct node{
ll lnum , rnum , lsum , rsum , sum , num , la;
}tree[maxn];
node conbine(node a,node b){
if(a.num == 0) return b;
node ans;
ans.la = 0;
ans.lnum = a.lnum;
ans.rnum = b.rnum;
ans.lsum = a.lsum;
ans.rsum = b.rsum;
ans.sum = a.sum + b.sum;
ans.num = a.num + b.num;
if(a.rnum != b.lnum){
if(ans.lsum == a.num){
ans.lsum += b.lsum;
}
if(ans.rsum == b.num){
ans.rsum += a.rsum;
}
ans.sum += a.rsum * b.lsum;
// printf ("******%d %d %d %d\n",a.num,b.num,a.rsum , b.lsum);
}
return ans;
}
void pushup(int rt){
tree[rt] = conbine(tree[rt << 1] , tree[rt << 1 | 1]);
}
void pushdown(int rt){
if(tree[rt].la == 0) return ;
tree[rt << 1].lnum ^= 1;
tree[rt << 1].rnum ^= 1;
tree[rt << 1 | 1].lnum ^= 1;
tree[rt << 1 | 1].rnum ^= 1;
tree[rt << 1].la ^= 1;
tree[rt << 1 | 1].la ^= 1;
tree[rt].la = 0;
}
void update(int L,int R,int l , int r,int rt){
if(L <= l && R >= r){
tree[rt].lnum ^= 1;
tree[rt].rnum ^= 1;
tree[rt].la ^= 1;
return ;
}
pushdown(rt);
int mid = (l + r) / 2;
if(L <= mid) update(L , R , l , mid , rt << 1);
if(R > mid) update(L , R , mid + 1 , r , rt << 1 | 1);
pushup(rt);
}
void build(int l, int r, int rt){
if(l == r){
tree[rt].lnum = x[l];
tree[rt].rnum = x[l];
// tree[rt].lnum = tree[rt].rnum = 1;
tree[rt].lsum = tree[rt].rsum = 1;
tree[rt].sum = tree[rt].num = 1;
return ;
}
int mid = (l + r) / 2;
build(l , mid , rt << 1);
build(mid + 1 , r , rt << 1 | 1);
pushup(rt);
}
node query(int L ,int R,int l,int r,int rt){
node ans = {0 , 0 , 0 , 0 , 0 , 0 , 0};
if(L <= l && R >= r){
return tree[rt];
}
pushdown(rt);
int mid = (l + r) / 2;
if(L <= mid) ans = conbine(ans , query(L , R , l , mid, rt << 1));
if(R > mid) ans = conbine(ans , query(L , R , mid + 1 , r , rt << 1 | 1));
return ans;
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i ++){
scanf("%d",&x[i]);
}
build(1 , n , 1);
while(m --){
int op , l , r;
scanf("%d%d%d",&op,&l,&r);
if(op == 1){
update(l , r , 1 , n , 1);
}
if(op == 2){
printf ("%lld\n",query(l , r , 1 , n , 1).sum);
}
}
return 0;
}