卧薪尝胆,厚积薄发。
SCOI2010 序列操作
Date: Tue Sep 11 19:18:41 CST 2018 In Category: NoCategory

Description:

一个 $01$ 序列,五种操作:区间清零,区间清一,区间取反,区间求和,区间求最长连续 $1$ 。
$1\le n \le 10^5$

Solution:

前两个都很好实现,重要的是区间取反,维护区间和,区间前缀零个数,区间前缀一个数,区间后缀零个数,区间后缀一个数,区间最大连续零个数,区间最大连续一个数,区间是否全为零 $/$ 全为一八个值,还有一个 $tag$ ,取反时把 $0/1$ 相关的信息交换即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
int n,m;
#define MAXN 100010
int val[MAXN];
struct node
{
int lc,rc,l,r;
int sum,llen[2],rlen[2],mlen[2],cov,tag;
node(){sum = llen[0] = llen[1] = rlen[0] = rlen[1] = mlen[0] = mlen[1] = 0;cov = tag = -1;}
}t[MAXN << 1];
int ptr = 0;
int newnode(){return ++ptr;}
int root;
#define mid ((l + r) >> 1)
void merge(node &rt,node lc,node rc)
{
rt.sum = lc.sum + rc.sum;
rt.cov = -1;
if(lc.cov == 0 && rc.cov == 0)rt.cov = 0;
if(lc.cov == 1 && rc.cov == 1)rt.cov = 1;
rt.llen[0] = lc.llen[0];if(lc.cov == 0)rt.llen[0] = lc.r - lc.l + 1 + rc.llen[0];
rt.rlen[0] = rc.rlen[0];if(rc.cov == 0)rt.rlen[0] = rc.r - rc.l + 1 + lc.rlen[0];
rt.mlen[0] = max(max(lc.mlen[0],rc.mlen[0]),lc.rlen[0] + rc.llen[0]);
rt.llen[1] = lc.llen[1];if(lc.cov == 1)rt.llen[1] = lc.r - lc.l + 1 + rc.llen[1];
rt.rlen[1] = rc.rlen[1];if(rc.cov == 1)rt.rlen[1] = rc.r - rc.l + 1 + lc.rlen[1];
rt.mlen[1] = max(max(lc.mlen[1],rc.mlen[1]),lc.rlen[1] + rc.llen[1]);
return;
}
void set(int rt,int k)
{
t[rt].sum = (t[rt].r - t[rt].l + 1) * k;
t[rt].llen[k] = t[rt].rlen[k] = t[rt].mlen[k] = t[rt].r - t[rt].l + 1;
t[rt].llen[k ^ 1] = t[rt].rlen[k ^ 1] = t[rt].mlen[k ^ 1] = 0;
t[rt].tag = t[rt].cov = k;
return;
}
void build(int &rt,int l,int r)
{
rt = newnode();
t[rt].l = l;t[rt].r = r;
if(l == r){set(rt,val[l]);return;}
build(t[rt].lc,l,mid);
build(t[rt].rc,mid + 1,r);
merge(t[rt],t[t[rt].lc],t[t[rt].rc]);
return;
}
void flp(int rt)
{
t[rt].sum = t[rt].r - t[rt].l + 1 - t[rt].sum;
if(t[rt].cov != -1)t[rt].cov = t[rt].cov ^ 1;
swap(t[rt].llen[0],t[rt].llen[1]);
swap(t[rt].rlen[0],t[rt].rlen[1]);
swap(t[rt].mlen[0],t[rt].mlen[1]);
return;
}
void pushdown(int rt)
{
if(t[rt].tag == -1)return;
if(t[rt].tag == 0){set(t[rt].lc,0);set(t[rt].rc,0);t[rt].tag = -1;}
if(t[rt].tag == 1){set(t[rt].lc,1);set(t[rt].rc,1);t[rt].tag = -1;}
if(t[rt].tag == 2)
{
int k = t[t[rt].lc].tag;
if(k == 0)set(t[rt].lc,1);
if(k == 1)set(t[rt].lc,0);
if(k == 2 || k == -1)
{
flp(t[rt].lc);
if(k == 2)t[t[rt].lc].tag = -1;
else t[t[rt].lc].tag = 2;
}
k = t[t[rt].rc].tag;
if(k == 0)set(t[rt].rc,1);
if(k == 1)set(t[rt].rc,0);
if(k == 2 || k == -1)
{
flp(t[rt].rc);
if(k == 2)t[t[rt].rc].tag = -1;
else t[t[rt].rc].tag = 2;
}
t[rt].tag = -1;
}
return;
}
void era(int rt,int L,int R,int l,int r)
{
pushdown(rt);
if(L <= l && r <= R)
{
set(rt,0);
return;
}
if(L <= mid)era(t[rt].lc,L,R,l,mid);
if(R > mid)era(t[rt].rc,L,R,mid + 1,r);
merge(t[rt],t[t[rt].lc],t[t[rt].rc]);
return;
}
void add(int rt,int L,int R,int l,int r)
{
pushdown(rt);
if(L <= l && r <= R)
{
set(rt,1);
return;
}
if(L <= mid)add(t[rt].lc,L,R,l,mid);
if(R > mid)add(t[rt].rc,L,R,mid + 1,r);
merge(t[rt],t[t[rt].lc],t[t[rt].rc]);
return;
}
void rev(int rt,int L,int R,int l,int r)
{
pushdown(rt);
if(L <= l && r <= R)
{
flp(rt);
t[rt].tag = 2;
return;
}
if(L <= mid)rev(t[rt].lc,L,R,l,mid);
if(R > mid)rev(t[rt].rc,L,R,mid + 1,r);
merge(t[rt],t[t[rt].lc],t[t[rt].rc]);
return;
}
node qry(int rt,int L,int R,int l,int r)
{
if(L <= l && r <= R)return t[rt];
pushdown(rt);
if(R <= mid)return qry(t[rt].lc,L,R,l,mid);
if(L > mid)return qry(t[rt].rc,L,R,mid + 1,r);
node res;
merge(res,qry(t[rt].lc,L,R,l,mid),qry(t[rt].rc,L,R,mid + 1,r));
return res;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= n;++i)scanf("%d",&val[i]);
build(root,1,n);
int opt,l,r;
for(int i = 1;i <= m;++i)
{
scanf("%d%d%d",&opt,&l,&r);++l;++r;
switch(opt)
{
case 0:{era(root,l,r,1,n);break;}
case 1:{add(root,l,r,1,n);break;}
case 2:{rev(root,l,r,1,n);break;}
case 3:{printf("%d\n",qry(root,l,r,1,n).sum);break;}
case 4:{printf("%d\n",qry(root,l,r,1,n).mlen[1]);break;}
}
}
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡