题目链接
普通线段树,只不过要维护的东西有点多:
struct Node
{
int l, r;
int sum0, sum1;//0,1的总和
bool flag0;//全0标记
bool flag1;//全1标记
int add;//操作延迟标记
int sumc0;//最长连续0长度
int sumc1;//最长连续1长度
int ls1, rs1;//最长连续1前、后缀
int ls0, rs0;//最长连续0前、后缀
}tr[N<<2];
重点对于add的维护。我们设:
add == -1 无操作 add == 0 全变0操作
add == 1 全变1操作 add == 2 异或操作
我们把k操作覆盖在p节点上,可以执行:
void update(int p, int k)
{
if (k != 2)
{//全1,全0,直接覆盖
tr[p].sum0 = tr[p].sumc0 = tr[p].ls0 = tr[p].rs0 = !k*(tr[p].r - tr[p].l +1);
tr[p].add = k;
tr[p].flag0 = !k;
tr[p].sum1 = tr[p].sumc1 = tr[p].ls1 = tr[p].rs1 = k*(tr[p].r - tr[p].l +1);
tr[p].flag1 = k;
}
else
{//对于异或操作的附加:
//2->-1 == 2; 2->0 == 1;
//2-> 1 == 0; 2->2 == -1;
tr[p].add = 1 - tr[p].add;//总结下来就是这个。
swap(tr[p].flag0, tr[p].flag1);
swap(tr[p].sum0, tr[p].sum1);
swap(tr[p].sumc0, tr[p].sumc1);
swap(tr[p].ls0, tr[p].ls1);
swap(tr[p].rs0, tr[p].rs1);//其余交换
}
}
于是本题得以解出。
下面是ac代码:
#include <iostream>
#include <queue>
#include <vector>
#include <cstdio>
#include <cstring>
#include <string>
#include <map>
#include <algorithm>
#include <cstdlib>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
const ll inf = 1e16;
int su[N];
struct Node
{
int l, r;
int sum0, sum1;
bool flag0;
bool flag1;
int add;
int sumc0;
int sumc1;
int ls1, rs1;
int ls0, rs0;
}tr[N<<2];
void update(int p, int k)
{
if (k != 2)
{
tr[p].sum0 = tr[p].sumc0 = tr[p].ls0 = tr[p].rs0 = !k*(tr[p].r - tr[p].l +1);
tr[p].add = k;
tr[p].flag0 = !k;
tr[p].sum1 = tr[p].sumc1 = tr[p].ls1 = tr[p].rs1 = k*(tr[p].r - tr[p].l +1);
tr[p].flag1 = k;
}
else
{
tr[p].add = 1 - tr[p].add;
swap(tr[p].flag0, tr[p].flag1);
swap(tr[p].sum0, tr[p].sum1);
swap(tr[p].sumc0, tr[p].sumc1);
swap(tr[p].ls0, tr[p].ls1);
swap(tr[p].rs0, tr[p].rs1);
}
}
void spread(int p)
{
if (tr[p].add == -1) return;
update(p<<1, tr[p].add);
update(p<<1|1, tr[p].add);
tr[p].add = -1;
}
void pushup(int p)
{
int l = p<<1, r = p<<1|1;
tr[p].flag0 = tr[l].flag0 && tr[r].flag0;
tr[p].flag1 = tr[l].flag1 && tr[r].flag1;
tr[p].sum0 = tr[l].sum0 + tr[r].sum0;
tr[p].sum1 = tr[l].sum1 + tr[r].sum1;
tr[p].sumc1 = max(tr[l].rs1+tr[r].ls1, max(tr[l].sumc1, tr[r].sumc1));
tr[p].sumc0 = max(tr[l].rs0+tr[r].ls0, max(tr[l].sumc0, tr[r].sumc0));
tr[p].ls1 = tr[l].flag1?tr[l].sum1+tr[r].ls1:tr[l].ls1;
tr[p].ls0 = tr[l].flag0?tr[l].sum0+tr[r].ls0:tr[l].ls0;
tr[p].rs1 = tr[r].flag1?tr[r].sum1+tr[l].rs1:tr[r].rs1;
tr[p].rs0 = tr[r].flag0?tr[r].sum0+tr[l].rs0:tr[r].rs0;
}
void build(int p, int l, int r)
{
tr[p].l = l; tr[p].r = r;
tr[p].add = -1;
if (l == r)
{
tr[p].sumc1 = tr[p].ls1 = tr[p].rs1 = tr[p].sum1 = su[l];
tr[p].flag1 = su[l];
tr[p].sumc0 = tr[p].ls0 = tr[p].rs0 = tr[p].sum0 = !su[l];
tr[p].flag0 = !su[l];
return;
}
int mid = (l + r) >> 1;
build(p<<1, l, mid);
build(p<<1|1, mid+1, r);
pushup(p);
}
void change(int p, int l, int r, int k)
{
if (l <= tr[p].l && tr[p].r <= r)
{
update(p, k);
return;
}
spread(p);
int mid = (tr[p].l + tr[p].r) >> 1;
if (l <= mid) change(p<<1, l, r, k);
if (r > mid) change(p<<1|1, l, r, k);
pushup(p);
}
int ask_n(int p, int l, int r)
{
if (l <= tr[p].l && tr[p].r <= r)
return tr[p].sum1;
spread(p);
int mid = (tr[p].l + tr[p].r) >> 1;
int val = 0;
if (l <= mid) val += ask_n(p<<1, l, r);
if (r > mid) val += ask_n(p<<1|1, l, r);
return val;
}
Node ask_c(int p, int l, int r)
{
if (l <= tr[p].l && tr[p].r <= r)
return tr[p];
spread(p);
int mid = (tr[p].l + tr[p].r) >> 1;
Node _l, _r;
if (l > mid)
return ask_c(p<<1|1, l, r);
else if (r <= mid)
return ask_c(p<<1, l, r);
_l = ask_c(p<<1, l, r);
_r = ask_c(p<<1|1, l, r);
Node te;
te.sumc1 = max(_l.rs1+_r.ls1, max(_l.sumc1, _r.sumc1));
te.ls1 = _l.flag1?_l.sum1+_r.ls1:_l.ls1;
te.rs1 = _r.flag1?_r.sum1+_l.rs1:_r.rs1;
return te;
}
int main()
{
int t;
cin >> t;
while(t--)
{
int n, m;
scanf("%d%d", &n, &m);
for (int i = 0; i < n; i++)
scanf("%d", &su[i]);
build(1, 0, n-1);
while(m--)
{
int op;
int l, r;
scanf("%d%d%d", &op, &l, &r);
if(op == 0)
change(1, l, r, 0);
if (op == 1)
change(1, l, r, 1);
if (op == 2)
change(1, l, r, 2);
if (op == 3)
printf("%d\n", ask_n(1, l, r));
if (op == 4)
{
Node te = ask_c(1, l, r);
printf("%d\n", te.sumc1);
}
}
}
}