BZOJ1858
這題是不錯的線段樹練習題.
注意查詢的時候返回一個節點而不是一個具體的數,否則無法做到合併信息並上傳.
還好一個小時就寫完啦
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define maxn 100010
using namespace std;
int n,m,a[maxn];
struct tree{
int l,r,l0,r0,z0,l1,r1,z1,num0,num1,sum1,sum0,tag;
bool rev;
tree*ls,*rs;
tree()
{
tag=-1;
rev=false;
l=r=l0=r0=z0=l1=r1=z1=num0=num1=sum1=sum0=0;
ls=rs=NULL;
}
void update()
{
l1=ls->l1+(ls->l1==ls->r-ls->l+1)*(rs->l1);
r1=rs->r1+(rs->r1==rs->r-rs->l+1)*(ls->r1);
l0=ls->l0+(ls->l0==ls->r-ls->l+1)*(rs->l0);
r0=rs->r0+(rs->r0==rs->r-rs->l+1)*(ls->r0);
z0=max(max(ls->z0,rs->z0),ls->r0+rs->l0);
z1=max(max(ls->z1,rs->z1),ls->r1+rs->l1);
num0=max(ls->r0+rs->l0,max(ls->z0,rs->z0));
num1=max(ls->r1+rs->l1,max(ls->z1,rs->z1));
sum1=ls->sum1+rs->sum1;
sum0=ls->sum0+rs->sum0;
}
void calc(int v)
{
rev=false;
tag=v;
if(v==0)
{
sum1=num1=l1=r1=z1=0;
sum0=num0=l0=r0=z0=r-l+1;
}
if(v==1)
{
sum1=num1=l1=r1=z1=r-l+1;
sum0=num0=l0=r0=z0=0;
}
}
void calcrev()
{
rev=!rev;
swap(l1,l0);swap(z1,z0);swap(r1,r0);
swap(sum1,sum0);swap(num1,num0);
}
void pushdown()
{
if(tag==0)
{
ls->calc(0);
rs->calc(0);
tag=-1;
}
if(tag==1)
{
ls->calc(1);
rs->calc(1);
tag=-1;
}
if(rev)
{
ls->calcrev();
rs->calcrev();
rev=false;
}
}
void build(int lx,int rx)
{
l=lx;r=rx;
if(l==r)
{
if(a[l]==1)
num0=sum0=l0=r0=z0=0,num1=sum1=l1=r1=z1=1;
else num0=sum0=l0=r0=z0=1,num1=sum1=l1=r1=z1=0;
return;
}
int mid=(l+r)>>1;
(ls=new tree)->build(l,mid);
(rs=new tree)->build(mid+1,r);
update();
}
void mod(int lx,int rx,int num)
{
if(l==lx&&r==rx)
{
if(num!=-1)
calc(num);
else calcrev();
return;
}
pushdown();
int mid=(l+r)>>1;
if(lx>mid) rs->mod(lx,rx,num);
else if(rx<=mid) ls->mod(lx,rx,num);
else ls->mod(lx,mid,num),rs->mod(mid+1,rx,num);
update();
}
int que1(int lx,int rx)
{
if(l==lx&&r==rx)
return sum1;
pushdown();
int mid=(l+r)>>1;
if(lx>mid) return rs->que1(lx,rx);
else if(rx<=mid) return ls->que1(lx,rx);
else return ls->que1(lx,mid)+rs->que1(mid+1,rx);
}
tree* quel1(int lx,int rx)
{
if(l==lx&&r==rx)
return this;
pushdown();
int mid=(l+r)>>1;
if(lx>mid) return rs->quel1(lx,rx);
else if(rx<=mid) return ls->quel1(lx,rx);
else
{
tree*p1=ls->quel1(lx,mid),*p2=rs->quel1(mid+1,rx);
tree*p=new tree;
p->l1=p1->l1+(p1->l1==p1->r-p1->l+1)*(p2->l1);
p->r1=p2->r1+(p2->r1==p2->r-p2->l+1)*(p1->r1);
p->l0=p1->l0+(p1->l0==p1->r-p1->l+1)*(p2->l0);
p->r0=p2->r0+(p2->r0==p2->r-p2->l+1)*(p1->r0);
p->z0=max(max(p1->z0,p2->z0),p1->r0+p2->l0);
p->z1=max(max(p1->z1,p2->z1),p1->r1+p2->l1);
p->num0=max(p1->r0+p2->l0,max(p1->z0,p2->z0));
p->num1=max(p1->r1+p2->l1,max(p1->z1,p2->z1));
p->sum1=p1->sum1+p2->sum1;
p->sum0=p1->sum0+p2->sum0;
return p;
}
}
void oupt()
{
cout<<l<<" "<<r<<" "<<l1<<" "<<z1<<" "<<r1<<endl;
if(l==r) return;
ls->oupt();
rs->oupt();
}
}*xtr;
int main()
{
// freopen("data.in","r",stdin);
// freopen("wode.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
(xtr=new tree)->build(1,n);
int x,y,opt;
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&opt,&x,&y);
x++;y++;
if(opt==0) xtr->mod(x,y,0);
if(opt==1) xtr->mod(x,y,1);
if(opt==2) xtr->mod(x,y,-1);
if(opt==3) printf("%d\n",xtr->que1(x,y));
if(opt==4) printf("%d\n",xtr->quel1(x,y)->num1);
}
return 0;
}