分别记录下0和1的连续段,异或就是把01值交换,不难,想清楚再敲
区间修改,区间异或,区间合并,线段树经典题
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls (rt<<1)
#define rs (rt<<1|1)
const int M = 100001;
int n,d;
int Xor[M<<2];
int cover[M<<2];
int lpa[M<<2][2],rpa[M<<2][2],mpa[M<<2][2],num[M<<2][2];
int L,R,op;
int max(int a, int b) { return a>b?a:b; }
int min(int a, int b) { return a<b?a:b; }
void swap(int &a, int &b) { int temp = a; a = b; b = temp; }
void Or(int rt)
{
if(cover[rt] != -1)
{
cover[rt] ^= 1;
}
else
{
Xor[rt] ^= 1;
}
}
void SWAP(int rt)
{
swap(lpa[rt][0], lpa[rt][1]);
swap(rpa[rt][0], rpa[rt][1]);
swap(mpa[rt][0], mpa[rt][1]);
swap(num[rt][0], num[rt][1]);
}
void pushup(int m, int len, int rt)
{
for(int i=0; i<2; i++)
{
lpa[rt][i] = lpa[ls][i];
rpa[rt][i] = rpa[rs][i];
if(lpa[rt][i] == len-(len>>1)) lpa[rt][i] += lpa[rs][i];
if(rpa[rt][i] == (len>>1)) rpa[rt][i] += rpa[ls][i];
mpa[rt][i] = rpa[ls][i] + lpa[rs][i];
mpa[rt][i] = max(mpa[rt][i], max(mpa[ls][i], mpa[rs][i]));
mpa[rt][i] = max(mpa[rt][i], max(lpa[rt][i], rpa[rt][i]));
num[rt][i] = num[ls][i] + num[rs][i];
}
if(cover[ls]!=-1 && cover[ls]==cover[rs]) cover[rt] = cover[ls];
else cover[rt] = -1;
}
void pushdown(int m, int len, int rt)
{
if(cover[rt] != -1)
{
d = cover[rt];
lpa[ls][d] = rpa[ls][d] = mpa[ls][d] = num[ls][d] = len-(len>>1);
lpa[ls][!d] = rpa[ls][!d] = mpa[ls][!d] = num[ls][!d] = 0;
cover[ls] = cover[rs] = d;
Xor[ls] = Xor[rs] = 0;
lpa[rs][d] = rpa[rs][d] = mpa[rs][d] = num[rs][d] = (len>>1);
lpa[rs][!d] = rpa[rs][!d] = mpa[rs][!d] = num[rs][!d] = 0;
}
else if(Xor[rt])
{
Or(ls);
SWAP(ls);
Or(rs);
SWAP(rs);
}
cover[rt] = -1;
Xor[rt] = 0;
}
void build(int l, int r, int rt)
{
Xor[rt] = 0;
if(l == r)
{
scanf("%d", &d);
cover[rt] = d;
lpa[rt][d] = rpa[rt][d] = mpa[rt][d] = num[rt][d] = 1;
lpa[rt][!d] = rpa[rt][!d] = mpa[rt][!d] = num[rt][!d] = 0;
}
else
{
int m = (l+r)>>1;
build(lson);
build(rson);
pushup(m,r-l+1,rt);
}
}
void update(int l, int r, int rt)
{
if(L<=l && r<=R)
{
if(op <= 1)
{
Xor[rt] = 0;
cover[rt] = op;
lpa[rt][op] = rpa[rt][op] = mpa[rt][op] = num[rt][op] = r-l+1;
lpa[rt][!op] = rpa[rt][!op] = mpa[rt][!op] = num[rt][!op] = 0;
}
else
{
SWAP(rt);
Or(rt);
}
}
else
{
int m = (l+r)>>1;
pushdown(m,r-l+1,rt);
if(L <= m) update(lson);
if(m < R) update(rson);
pushup(m,r-l+1,rt);
}
}
int query(int l, int r, int rt)
{
if(L<=l && r<=R)
{
if(op == 3) return num[rt][1];
else return mpa[rt][1];
}
else
{
int m = (l+r)>>1;
pushdown(m,r-l+1,rt);
if(op == 3)
{
int ans = 0;
if(L <= m) ans = query(lson);
if(m < R) ans += query(rson);
return ans;
}
else
{
int ans = min(rpa[ls][1],m-L+1) + min(lpa[rs][1],R-m);
if(L <= m) ans = max(ans, query(lson));
if(m < R) ans = max(ans, query(rson));
return ans;
}
}
}
int main()
{
int m;
int cas;
scanf("%d", &cas);
while(cas--)
{
scanf("%d%d", &n, &m);
build(0,n-1,1);
while(m--)
{
scanf("%d%d%d", &op, &L, &R);
if(op >= 3) printf("%d\n", query(0,n-1,1));
else update(0,n-1,1);
}
}
return 0;
}
区间修改,区间异或,区间合并,线段树经典题