【洛谷】 P2572 [SCOI2010]序列操作 (线段树)
作者:互联网
P2572 [SCOI2010]序列操作
对于区间覆盖,我们都习以为常了,对于连续的\(1\)这种线段树区间连续问题,维护左儿子右端点连续最大和右儿子左端点连续最大即可解决,那么取反操作就是将区间连续的\(1\)和连续的\(0\)的数量交换,分别对\(0\)和\(1\)维护连续也可解决,再看懒标记的问题,首先赋值会覆盖取反标记,然后取反标记的时候,如果当前区间有赋值标记,那么赋值标记也应该取反!!!!(这里卡了我好久,调了半天),最后就是查询连续最大值,可以当成一个板子吧,分三种情况return。
#include <bits/stdc++.h>
using namespace std;
const int N=1e6+10;
const int mod=1e9+7;
#define ll long long
#define pb push_back
int n,m;
int a[N];
struct Node{
int l,r;
int tag;
int rev;
int sum;
int mx0;
int lmx0,rmx0;
int mx1;
int lmx1,rmx1;
}tr[N<<4];
void push_up(int u){
tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
if(tr[u<<1].mx1==tr[u<<1].r-tr[u<<1].l+1) tr[u].lmx1=tr[u<<1].mx1+tr[u<<1|1].lmx1;
else tr[u].lmx1=tr[u<<1].lmx1;
if(tr[u<<1|1].mx1==tr[u<<1|1].r-tr[u<<1|1].l+1) tr[u].rmx1=tr[u<<1|1].mx1+tr[u<<1].rmx1;
else tr[u].rmx1=tr[u<<1|1].rmx1;
if(tr[u<<1].mx0==tr[u<<1].r-tr[u<<1].l+1) tr[u].lmx0=tr[u<<1].mx0+tr[u<<1|1].lmx0;
else tr[u].lmx0=tr[u<<1].lmx0;
if(tr[u<<1|1].mx0==tr[u<<1|1].r-tr[u<<1|1].l+1) tr[u].rmx0=tr[u<<1|1].mx0+tr[u<<1].rmx0;
else tr[u].rmx0=tr[u<<1|1].rmx0;
tr[u].mx1=max({tr[u<<1].mx1,tr[u<<1|1].mx1,tr[u<<1].rmx1+tr[u<<1|1].lmx1});
tr[u].mx0=max({tr[u<<1].mx0,tr[u<<1|1].mx0,tr[u<<1].rmx0+tr[u<<1|1].lmx0});
}
void push_down(int u){
if(tr[u].tag!=-1){
tr[u].rev=0;
tr[u<<1].rev=tr[u<<1|1].rev=0;
if(tr[u].tag==0){
tr[u<<1].sum=tr[u<<1].mx1=tr[u<<1].lmx1=tr[u<<1].rmx1=0;
tr[u<<1].mx0=tr[u<<1].lmx0=tr[u<<1].rmx0=tr[u<<1].r-tr[u<<1].l+1;
tr[u<<1].tag=0;
tr[u<<1|1].sum=tr[u<<1|1].mx1=tr[u<<1|1].lmx1=tr[u<<1|1].rmx1=0;
tr[u<<1|1].mx0=tr[u<<1|1].lmx0=tr[u<<1|1].rmx0=tr[u<<1|1].r-tr[u<<1|1].l+1;
tr[u<<1|1].tag=0;
}
if(tr[u].tag==1){
tr[u<<1].sum=tr[u<<1].mx1=tr[u<<1].lmx1=tr[u<<1].rmx1=tr[u<<1].r-tr[u<<1].l+1;
tr[u<<1].mx0=tr[u<<1].lmx0=tr[u<<1].rmx0=0;
tr[u<<1].tag=1;
tr[u<<1|1].sum=tr[u<<1|1].mx1=tr[u<<1|1].lmx1=tr[u<<1|1].rmx1=tr[u<<1|1].r-tr[u<<1|1].l+1;
tr[u<<1|1].mx0=tr[u<<1|1].lmx0=tr[u<<1|1].rmx0=0;
tr[u<<1|1].tag=1;
}
tr[u].tag=-1;
}
if(tr[u].rev){
if(tr[u<<1].tag!=-1) tr[u<<1].tag^=1;
else tr[u<<1].rev^=1;
if(tr[u<<1|1].tag!=-1) tr[u<<1|1].tag^=1;
else tr[u<<1|1].rev^=1;
tr[u<<1].sum=tr[u<<1].r-tr[u<<1].l+1-tr[u<<1].sum;
swap(tr[u<<1].mx0,tr[u<<1].mx1);
swap(tr[u<<1].lmx0,tr[u<<1].lmx1);
swap(tr[u<<1].rmx0,tr[u<<1].rmx1);
tr[u<<1|1].sum=tr[u<<1|1].r-tr[u<<1|1].l+1-tr[u<<1|1].sum;
swap(tr[u<<1|1].mx0,tr[u<<1|1].mx1);
swap(tr[u<<1|1].lmx0,tr[u<<1|1].lmx1);
swap(tr[u<<1|1].rmx0,tr[u<<1|1].rmx1);
tr[u].rev=0;
}
}
void build(int u,int l,int r){
if(l==r){
tr[u]={l,r,-1,0,a[l],1-a[l],1-a[l],1-a[l],a[l],a[l],a[l]};
return;
}
tr[u]={l,r,-1,0,0,0,0,0,0,0,0};
int mid=(l+r)>>1;
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
push_up(u);
}
void update(int u,int L,int R,int k){
if(tr[u].l>=L && tr[u].r<=R){
if(k==0){
tr[u].sum=tr[u].mx1=tr[u].lmx1=tr[u].rmx1=0;
tr[u].mx0=tr[u].lmx0=tr[u].rmx0=tr[u].r-tr[u].l+1;
tr[u].tag=0;
tr[u].rev=0;
}
else if(k==1){
tr[u].sum=tr[u].mx1=tr[u].lmx1=tr[u].rmx1=tr[u].r-tr[u].l+1;
tr[u].mx0=tr[u].lmx0=tr[u].rmx0=0;
tr[u].tag=1;
tr[u].rev=0;
}
else if(k==2){
tr[u].sum=tr[u].r-tr[u].l+1-tr[u].sum;
swap(tr[u].mx0,tr[u].mx1);
swap(tr[u].lmx0,tr[u].lmx1);
swap(tr[u].rmx0,tr[u].rmx1);
tr[u].rev^=1;
if(tr[u].tag!=-1) tr[u].tag^=1;
}
return;
}
push_down(u);
int mid=(tr[u].l+tr[u].r)>>1;
if(L<=mid) update(u<<1,L,R,k);
if(R>mid) update(u<<1|1,L,R,k);
push_up(u);
}
int query1(int u,int L,int R){
if(tr[u].l>=L && tr[u].r<=R){
return tr[u].sum;
}
push_down(u);
int mid=(tr[u].l+tr[u].r)>>1;
int res=0;
if(L<=mid) res+=query1(u<<1,L,R);
if(R>mid) res+=query1(u<<1|1,L,R);
return res;
}
Node query2(int u,int L,int R){
if(tr[u].l>=L && tr[u].r<=R){
return tr[u];
}
push_down(u);
int mid=(tr[u].l+tr[u].r)>>1;
if(L<=mid && R>mid){
Node res1,res2,res;
res1=query2(u<<1,L,R);
res2=query2(u<<1|1,L,R);
if(res1.mx1==res1.r-res1.l+1) res.lmx1=res1.mx1+res2.lmx1;
else res.lmx1=res1.lmx1;
if(res2.mx1==res2.r-res2.l+1) res.rmx1=res1.rmx1+res2.mx1;
else res.rmx1=res2.rmx1;
res.mx1=max({res1.mx1,res2.mx1,res1.rmx1+res2.lmx1});
return res;
}
else if(L<=mid) return query2(u<<1,L,R);
else if(R>mid) return query2(u<<1|1,L,R);
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
build(1,1,n);
while(m--){
int op,l,r;
scanf("%d %d %d",&op,&l,&r);
l++,r++;
if(op==0){
update(1,l,r,0);
}
else if(op==1){
update(1,l,r,1);
}
else if(op==2){
update(1,l,r,2);
}
else if(op==3){
printf("%d\n",query1(1,l,r));
}
else if(op==4){
printf("%d\n",query2(1,l,r).mx1);
}
}
return 0;
}
标签:洛谷,标记,int,res,tr,取反,连续,P2572,SCOI2010 来源: https://www.cnblogs.com/lr599909928/p/15602039.html