Acestar @ 2020-02-12 23:13:59
样例过了,
线段树题,写法每个人的都有差异,望各位
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int N = 1e5+10;
int a[N];
int sum[N<<2],maxs[N<<2][2],lmax[N<<2][2],rmax[N<<2][2];
//sum[i]: 以i为根的子树的叶节点中1的个数。
//maxs[i][0/1]: 以i为根的子树的叶节点中连续的0/1的个数。
//lmax[i][0/1]: 以i为根的子树的叶节点中从左开始连续的0/1的个数。
//rmax[i][0/1]: 以i为根的子树的叶节点中从右开始连续的0/1的个数。
int tag[N<<2],rev[N<<2],len[N<<2];
//tag[i]=-1/0/1 (lazytag): -1表示没有赋值,0表示赋值为0,1表示赋值为1。
//rev[i]=0/1 (reverse): 0表示没有反转,1表示反转。
//len[i]: 以i为根的子树的叶节点个数。
int read()
{
int x=0;
char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
return x;
}
void pushup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
lmax[rt][1]=(maxs[rt<<1][1]==len[rt<<1])?len[rt<<1]+lmax[rt<<1|1][1]:lmax[rt<<1][1];
lmax[rt][0]=(maxs[rt<<1][0]==len[rt<<1])?len[rt<<1]+lmax[rt<<1|1][0]:lmax[rt<<1][0];
rmax[rt][1]=(maxs[rt<<1|1][1]==len[rt<<1|1])?len[rt<<1|1]+rmax[rt<<1][1]:rmax[rt<<1|1][1];
rmax[rt][0]=(maxs[rt<<1|1][0]==len[rt<<1|1])?len[rt<<1|1]+rmax[rt<<1][0]:rmax[rt<<1|1][0];
maxs[rt][1]=max(max(lmax[rt<<1][1],rmax[rt<<1|1][1]),rmax[rt<<1][1]+lmax[rt<<1|1][1]);
maxs[rt][0]=max(max(lmax[rt<<1][0],rmax[rt<<1|1][0]),rmax[rt<<1][0]+lmax[rt<<1|1][0]);
}
void build(int l,int r,int rt)
{
tag[rt]=-1;
len[rt]=r-l+1;
if(l==r)
{
sum[rt]=a[l];
lmax[rt][1]=rmax[rt][1]=maxs[rt][1]=a[l];
lmax[rt][0]=rmax[rt][0]=maxs[rt][0]=a[l]^1;
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void pushdown(int rt)
{
if(tag[rt]!=-1)
{
sum[rt<<1]=lmax[rt<<1][1]=rmax[rt<<1][1]=maxs[rt<<1][1]=tag[rt]*len[rt<<1];
sum[rt<<1|1]=lmax[rt<<1|1][1]=rmax[rt<<1|1][1]=maxs[rt<<1|1][1]=tag[rt]*len[rt<<1|1];
lmax[rt<<1][0]=rmax[rt<<1][0]=maxs[rt<<1][0]=len[rt<<1]-sum[rt<<1];
lmax[rt<<1|1][0]=rmax[rt<<1|1][0]=maxs[rt<<1|1][0]=len[rt<<1|1]-sum[rt<<1|1];
tag[rt<<1]=tag[rt<<1|1]=tag[rt];
rev[rt]=rev[rt<<1]=rev[rt<<1|1]=0;
tag[rt]=-1;
}
if(rev[rt])
{
sum[rt<<1]=len[rt<<1]-sum[rt<<1];
swap(maxs[rt<<1][1],maxs[rt<<1][0]);
swap(lmax[rt<<1][1],lmax[rt<<1][0]);
swap(rmax[rt<<1][1],rmax[rt<<1][0]);
if(tag[rt<<1]!=-1) tag[rt<<1]^=1;
else rev[rt<<1]^=1;
sum[rt<<1|1]=len[rt<<1|1]-sum[rt<<1|1];
swap(maxs[rt<<1|1][1],maxs[rt<<1|1][0]);
swap(lmax[rt<<1|1][1],lmax[rt<<1|1][0]);
swap(rmax[rt<<1|1][1],rmax[rt<<1|1][0]);
if(tag[rt<<1|1]!=-1) tag[rt<<1|1]^=1;
else rev[rt<<1|1]^=1;
rev[rt]=0;
}
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
if(c<=1)
{
sum[rt]=c*len[rt];
lmax[rt][1]=rmax[rt][1]=maxs[rt][1]=c*len[rt];
lmax[rt][0]=rmax[rt][0]=maxs[rt][0]=len[rt]-sum[rt];
tag[rt]=c;
rev[rt]=0;
}
else
{
sum[rt]=len[rt]-sum[rt];
swap(maxs[rt][1],maxs[rt][0]);
swap(lmax[rt][1],lmax[rt][0]);
swap(rmax[rt][1],rmax[rt][0]);
rev[rt]^=1;
}
return;
}
pushdown(rt);
int mid=(l+r)>>1;
if(L<=mid) update(L,R,c,l,mid,rt<<1);
if(mid<R) update(L,R,c,mid+1,r,rt<<1|1);
pushup(rt);
}
int qry_sum(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R) return sum[rt];
pushdown(rt);
int ret=0;
int mid=(l+r)>>1;
if(L<=mid) ret+=qry_sum(L,R,l,mid,rt<<1);
if(mid<R) ret+=qry_sum(L,R,mid+1,r,rt<<1|1);
return ret;
}
int qry_max(int L,int R,int l,int r,int rt)
{
if(L==l&&r==R) return maxs[rt][1];
pushdown(rt);
int mid=(l+r)>>1;
if(R<=mid) return qry_max(L,R,l,mid,rt<<1);
else if(mid<L) return qry_max(L,R,mid+1,r,rt<<1|1);
else return max(max(qry_max(L,mid,l,mid,rt<<1),qry_max(mid+1,R,mid+1,r,rt<<1|1)),
min(rmax[rt<<1][1],mid-L+1)+min(lmax[rt<<1|1][1],R-mid));
}
int main()
{
int n=read(),m=read();
for(int i=1; i<=n; i++) a[i]=read();
build(1,n,1);
while(m--)
{
int t=read(),l=read()+1,r=read()+1;
if(t<=2) update(l,r,t,1,n,1);
else if(t==3) printf("%d\n",qry_sum(l,r,1,n,1));
else printf("%d\n",qry_max(l,r,1,n,1));
}
return 0;
}
by Thomas_ @ 2020-02-12 23:14:15
现在都在关心名字
by Andysun06 @ 2020-02-12 23:21:28
我不是大佬,不能看
by 览遍千秋 @ 2020-02-13 07:08:43
为啥不写珂朵莉树呢
by Acestar @ 2020-02-13 07:57:34
@expect 原因很简单——我太菜了,不会