卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽卧槽
if (l[k]==x&&r[k]==y) 写成了 if(l[k]==r[k]) 。。。。
线段树1s变O(n2)。。。
线段树维护一坨信息。。没了。。
#include<iostream>
#include<cstdio>
#define N 400005
using namespace std;
int n,m,top,cnt;
int l[N],r[N],l0[N],r0[N],l1[N],r1[N],sum0[N],sum1[N],mx0[N],mx1[N],size[N],tag[N];
int a[N>>2],stack[N>>2];
inline int read()
{
int a=0,f=1; char c=getchar();
while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
return a*f;
}
inline void pushup(int k)
{
int L=k<<1,R=k<<1|1;
l0[k]=l0[L]; r0[k]=r0[R];
l1[k]=l1[L]; r1[k]=r1[R];
if (l0[L]==size[L]) l0[k]+=l0[R];
if (l1[L]==size[L]) l1[k]+=l1[R];
if (r0[R]==size[R]) r0[k]+=r0[L];
if (r1[R]==size[R]) r1[k]+=r1[L];
sum0[k]=sum0[L]+sum0[R];
sum1[k]=sum1[L]+sum1[R];
mx0[k]=max(r0[L]+l0[R],max(mx0[L],mx0[R]));
mx1[k]=max(r1[L]+l1[R],max(mx1[L],mx1[R]));
}
inline void pushdown(int k)
{
if (l[k]==r[k]) return;
cnt++;
int L=k<<1,R=k<<1|1;
if (tag[k]!=-1)
{
int tmp=tag[k];
tag[k]=-1;
if (tmp==0)
{
l0[L]=r0[L]=mx0[L]=sum0[L]=size[L];
l1[L]=r1[L]=mx1[L]=sum1[L]=0;
l0[R]=r0[R]=mx0[R]=sum0[R]=size[R];
l1[R]=r1[R]=mx1[R]=sum1[R]=0;
tag[L]=tag[R]=0;
}
else if (tmp==1)
{
l0[L]=r0[L]=mx0[L]=sum0[L]=0;
l1[L]=r1[L]=mx1[L]=sum1[L]=size[L];
l0[R]=r0[R]=mx0[R]=sum0[R]=0;
l1[R]=r1[R]=mx1[R]=sum1[R]=size[R];
tag[L]=tag[R]=1;
}
else
{
swap(l0[L],l1[L]); swap(r0[L],r1[L]); swap(sum0[L],sum1[L]); swap(mx0[L],mx1[L]);
swap(l0[R],l1[R]); swap(r0[R],r1[R]); swap(sum0[R],sum1[R]); swap(mx0[R],mx1[R]);
if (tag[L]==-1) tag[L]=2;
else if (tag[L]==0) tag[L]=1;
else if (tag[L]==1) tag[L]=0;
else tag[L]=-1;
if (tag[R]==-1) tag[R]=2;
else if (tag[R]==0) tag[R]=1;
else if (tag[R]==1) tag[R]=0;
else tag[R]=-1;
}
}
}
void build(int k,int x,int y)
{
l[k]=x; r[k]=y; size[k]=r[k]-l[k]+1; tag[k]=-1;
if (l[k]==r[k])
{
if (a[l[k]]==0) l0[k]=r0[k]=mx0[k]=sum0[k]=1;
else l1[k]=r1[k]=mx1[k]=sum1[k]=1;
return;
}
int mid=l[k]+r[k]>>1;
build(k<<1,x,mid); build(k<<1|1,mid+1,y);
pushup(k);
}
void change(int k,int x,int y,int val)
{
pushdown(k);
if (l[k]==x&&r[k]==y)
{
tag[k]=val;
if (val==0)
{
l0[k]=r0[k]=mx0[k]=sum0[k]=size[k];
l1[k]=r1[k]=mx1[k]=sum1[k]=0;
}
else
{
l0[k]=r0[k]=mx0[k]=sum0[k]=0;
l1[k]=r1[k]=mx1[k]=sum1[k]=size[k];
}
return;
}
int mid=l[k]+r[k]>>1;
if (y<=mid) change(k<<1,x,y,val);
else if (x>mid) change(k<<1|1,x,y,val);
else change(k<<1,x,mid,val),change(k<<1|1,mid+1,y,val);
pushup(k);
}
void rever(int k,int x,int y)
{
pushdown(k);
if (l[k]==x&&r[k]==y)
{
tag[k]=2;
swap(l0[k],l1[k]); swap(r0[k],r1[k]); swap(sum0[k],sum1[k]); swap(mx0[k],mx1[k]);
return;
}
int mid=l[k]+r[k]>>1;
if (y<=mid) rever(k<<1,x,y);
else if (x>mid) rever(k<<1|1,x,y);
else rever(k<<1,x,mid),rever(k<<1|1,mid+1,y);
pushup(k);
}
int query1(int k,int x,int y)
{
if (l[k]==x&&r[k]==y) return sum1[k];
pushdown(k);
int mid=l[k]+r[k]>>1;
if (y<=mid) return query1(k<<1,x,y);
else if (x>mid) return query1(k<<1|1,x,y);
else return query1(k<<1,x,mid)+query1(k<<1|1,mid+1,y);
}
void query2(int k,int x,int y)
{
if (l[k]==x&&r[k]==y)
{
stack[++top]=k;
return;
}
pushdown(k);
int mid=l[k]+r[k]>>1;
if (y<=mid) query2(k<<1,x,y);
else if (x>mid) query2(k<<1|1,x,y);
else query2(k<<1,x,mid),query2(k<<1|1,mid+1,y);
}
int work()
{
int nowl0=l0[stack[1]],nowr0=r0[stack[1]],nowl1=l1[stack[1]],nowr1=r1[stack[1]],nowsum0=sum0[stack[1]],nowsum1=sum1[stack[1]],nowmx0=mx0[stack[1]],nowmx1=mx1[stack[1]],nowsize=size[stack[1]];
for (int i=2;i<=top;i++)
{
int lastl0=nowl0,lastl1=nowl1,lastr0=nowr0,lastr1=nowr1,lastsum0=nowsum0,lastsum1=nowsum1,lastmx0=nowmx0,lastmx1=nowmx1,lastsize=nowsize;
int R=stack[i];
nowl0=lastl0; nowr0=r0[R];
nowl1=lastl1; nowr1=r1[R];
if (lastl0==lastsize) nowl0+=l0[R];
if (lastl1==lastsize) nowl1+=l1[R];
if (r0[R]==size[R]) nowr0+=lastr0;
if (r1[R]==size[R]) nowr1+=lastr1;
nowsum0=lastsum0+sum0[R];
nowsum1=lastsum1+sum1[R];
nowmx0=max(lastr0+l0[R],max(lastmx0,mx0[R]));
nowmx1=max(lastr1+l1[R],max(lastmx1,mx1[R]));
nowsize=lastsize+size[R];
}
return nowmx1;
}
int main()
{
n=read(); m=read();
for (int i=1;i<=n;i++) a[i]=read();
build(1,1,n);
int tmp;
for (int i=1;i<=m;i++)
{
int opt=read(),x=read()+1,y=read()+1;
switch (opt)
{
case 0:
change(1,x,y,0);
break;
case 1:
change(1,x,y,1);
break;
case 2:
rever(1,x,y);
break;
case 3:
printf("%d\n",query1(1,x,y));
break;
case 4:
top=0;
query2(1,x,y);
printf("%d\n",work());
break;
}
}
return 0;
}
本文详细介绍了一种高效的数据结构——线段树,并通过具体的代码示例展示了如何使用线段树来解决区间更新和查询等问题。文章深入浅出地解释了线段树的基本原理、构建方法、更新操作及区间翻转等高级应用。
1020

被折叠的 条评论
为什么被折叠?



