对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
Day2
非常麻烦的线段树模板(其实还是值得一写的......然而我直接抄了代码orz)
这道题需要记录很多东西......max,lmax,rmax,sum,tag(覆盖标记),rev(取反标记)
特别需要注意的是:如果先取反再覆盖,那么取反就没用了,直接删除取反标记;如果先覆盖再取反,只需要将覆盖标记取反,不需要打取反标记。
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define LL long long #define pa pair<int,int> #define MAXN 100005 using namespace std; struct tree_type { int l,r,tag,s[2],lx[2],rx[2],mx[2]; bool rev; }t[MAXN*4]; int n,m,rx,mx,a[MAXN]; int read() { int ret=0,flag=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') flag=-1;ch=getchar();} while (ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();} return ret*flag; } void pushup(int k) { int l=t[k].l,r=t[k].r,mid=(l+r)>>1; F(i,0,1) { t[k].s[i]=t[k<<1].s[i]+t[k<<1|1].s[i]; t[k].lx[i]=t[k<<1].lx[i]; if (t[k<<1].lx[i]==mid-l+1) t[k].lx[i]+=t[k<<1|1].lx[i]; t[k].rx[i]=t[k<<1|1].rx[i]; if (t[k<<1|1].rx[i]==r-mid) t[k].rx[i]+=t[k<<1].rx[i]; t[k].mx[i]=max(t[k<<1].rx[i]+t[k<<1|1].lx[i],max(t[k<<1].mx[i],t[k<<1|1].mx[i])); } } void build(int k,int x,int y) { int l=t[k].l=x,r=t[k].r=y,mid=(l+r)>>1; t[k].tag=-1; t[k].rev=0; if (l==r) { F(i,0,1) t[k].s[i]=t[k].lx[i]=t[k].rx[i]=t[k].mx[i]=a[x]==i?1:0; return; } build(k<<1,l,mid); build(k<<1|1,mid+1,r); pushup(k); } void update(int k,int x) { t[k].tag=x; F(i,0,1) t[k].s[i]=t[k].lx[i]=t[k].rx[i]=t[k].mx[i]=x==i?(t[k].r-t[k].l+1):0; } void solverever(int k) { t[k].rev^=1; swap(t[k].s[0],t[k].s[1]); swap(t[k].lx[0],t[k].lx[1]); swap(t[k].rx[0],t[k].rx[1]); swap(t[k].mx[0],t[k].mx[1]); if (t[k].tag!=-1) { t[k].rev=0; t[k].tag^=1; return; } } void pushdown(int k) { if (t[k].tag!=-1) { int x=t[k].tag; update(k<<1,x); update(k<<1|1,x); t[k].tag=-1; t[k].rev=0; } if (t[k].rev) { solverever(k<<1); solverever(k<<1|1); t[k].rev=0; } } void change(int k,int x,int y,int z) { int l=t[k].l,r=t[k].r,mid=(l+r)>>1; if (l==x&&r==y) { update(k,z); return; } pushdown(k); if (y<=mid) change(k<<1,x,y,z); else if (x>mid) change(k<<1|1,x,y,z); else change(k<<1,x,mid,z),change(k<<1|1,mid+1,y,z); pushup(k); } void rever(int k,int x,int y) { int l=t[k].l,r=t[k].r,mid=(l+r)>>1; if (l==x&&r==y) { solverever(k); return; } pushdown(k); 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 getsum(int k,int x,int y) { int l=t[k].l,r=t[k].r,mid=(l+r)>>1; if (l==x&&r==y) return t[k].s[1]; pushdown(k); if (y<=mid) return getsum(k<<1,x,y); else if (x>mid) return getsum(k<<1|1,x,y); else return getsum(k<<1,x,mid)+getsum(k<<1|1,mid+1,y); } void query(int k,int x,int y) { int l=t[k].l,r=t[k].r,mid=(l+r)>>1; if (l==x&&r==y) { mx=max(mx,t[k].mx[1]); mx=max(mx,rx+t[k].lx[1]); if (t[k].s[1]==r-l+1) rx+=t[k].s[1]; else rx=t[k].rx[1]; return; } pushdown(k); if (y<=mid) query(k<<1,x,y); else if (x>mid) query(k<<1|1,x,y); else query(k<<1,x,mid),query(k<<1|1,mid+1,y); } int main() { n=read();m=read(); F(i,1,n) a[i]=read(); build(1,1,n); F(i,1,m) { int flag=read(),x=read(),y=read(); x++;y++; switch(flag) { 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",getsum(1,x,y));break; case 4:rx=mx=0;query(1,x,y);printf("%d\n",mx);break; } } return 0; }