bzoj1500 维修数列
Posted 友人A
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1500 维修数列相关的知识,希望对你有一定的参考价值。
这道题 我看了hzwer的代码 自己理会把 加油
#include<cstdio> #include<cstring> #include<algorithm> #include<queue> using namespace std; const int M=1000555,inf=1000000000; int read(){ int ans=0,f=1,c=getchar(); while(c<‘0‘||c>‘9‘) {if(c==‘-‘) f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){ans=ans*10+(c-‘0‘); c=getchar();} return ans*f; } queue<int>q; int n,m,root,cnt; int c[M][2],a[M],fa[M],id[M]; int size[M],sum[M],v[M],mx[M],lx[M],rx[M]; bool tag[M],rev[M]; void up(int x){ int l=c[x][0],r=c[x][1]; sum[x]=sum[l]+sum[r]+v[x]; size[x]=size[l]+size[r]+1; mx[x]=max(mx[l],mx[r]); mx[x]=max(mx[x],rx[l]+v[x]+lx[r]); lx[x]=max(lx[l],sum[l]+v[x]+lx[r]); rx[x]=max(rx[r],sum[r]+v[x]+rx[l]); } void down(int k){ int l=c[k][0],r=c[k][1]; if(tag[k]){ rev[k]=0; tag[k]=0; if(l) tag[l]=1,v[l]=v[k],sum[l]=v[k]*size[l]; if(r) tag[r]=1,v[r]=v[k],sum[r]=v[k]*size[r]; if(v[k]>=0){ if(l) lx[l]=rx[l]=mx[l]=sum[l]; if(r) lx[r]=rx[r]=mx[r]=sum[r]; } else{ if(l) lx[l]=rx[l]=0,mx[l]=v[k]; if(r) lx[r]=rx[r]=0,mx[r]=v[k]; } } if(rev[k]){ rev[k]=0; rev[l]^=1; rev[r]^=1; swap(lx[l],rx[l]); swap(lx[r],rx[r]); swap(c[l][0],c[l][1]); swap(c[r][0],c[r][1]); } } int find(int x,int rank){ down(x); int l=c[x][0],r=c[x][1]; if(size[l]+1==rank) return x; else if(size[l]>=rank) return find(l,rank); else return find(r,rank-size[l]-1); } void rotate(int x,int& k){ int y=fa[x],z=fa[y],l=0,r=1; if(c[y][1]==x) l=1,r=0; if(y==k) k=x; else{if(c[z][0]==y) c[z][0]=x; else c[z][1]=x;} fa[y]=x; fa[x]=z; fa[c[x][r]]=y; c[y][l]=c[x][r]; c[x][r]=y; up(y); up(x); } void splay(int x,int& k){ while(x!=k){ int y=fa[x],z=fa[y]; if(y!=k){ if(c[z][0]==y^c[y][0]==x) rotate(y,k); else rotate(x,k); } rotate(x,k); } } int split(int k,int tot){ int x=find(root,k),y=find(root,k+tot+1); splay(x,root); splay(y,c[x][1]); return c[y][0]; } void modify(int k,int tot,int w){ int x=split(k,tot),y=fa[x]; v[x]=w; sum[x]=w*size[x]; tag[x]=1; if(w>=0) lx[x]=rx[x]=mx[x]=sum[x]; else lx[x]=rx[x]=0,mx[x]=w; up(y); up(fa[y]); } void rec(int k){ if(!k) return ; int l=c[k][0],r=c[k][1]; rec(l); rec(r); q.push(k); fa[k]=c[k][0]=c[k][1]=0; rev[k]=tag[k]=0; } void eraser(int k,int tot){ int x=split(k,tot),y=fa[x]; rec(x); c[y][0]=0; up(y); up(fa[y]); } /*void build(int l,int r,int f){ if(l>r) return ; int mid=(l+r)>>1,now=id[mid],last=id[f]; if(l==r){ sum[now]=a[mid]; size[now]=1; tag[now]=0; rev[now]=0; if(a[l]>=0)lx[now]=rx[now]=mx[now]=a[mid]; else lx[now]=rx[now]=0,mx[now]=a[mid]; } else build(l,mid-1,mid),build(mid+1,r,mid); v[now]=a[mid]; fa[now]=last; up(now); c[last][mid>=f]=now; }*/ int build(int l,int r){ if(l>r) return 0; int m=(l+r)>>1,now=id[m]; tag[now]=rev[now]=0; v[now]=a[m]; c[now][0]=build(l,m-1); c[now][1]=build(m+1,r); for(int i=0;i<2;i++) if(c[now][i]) fa[c[now][i]]=now; up(now); return now; } void insert(int k,int tot){ for(int i=1;i<=tot;i++) a[i]=read(); for(int i=1;i<=tot;i++) if(!q.empty()) id[i]=q.front(),q.pop(); else id[i]=++cnt; int z=build(1,tot); int x=find(root,k+1),y=find(root,k+2); splay(x,root); splay(y,c[x][1]); fa[z]=y; c[y][0]=z; up(y); up(x); } void rever(int k,int tot){ int x=split(k,tot),y=fa[x]; if(!tag[x]){ rev[x]^=1; swap(c[x][0],c[x][1]); swap(lx[x],rx[x]); up(y); up(fa[y]); } } void push_ans(int k,int tot){ int x=split(k,tot); printf("%d\n",sum[x]); } int main() { n=read(); m=read(); mx[0]=a[1]=a[n+2]=-inf; for(int i=1;i<=n;i++) a[i+1]=read(); for(int i=1;i<=n+2;i++) id[i]=i; root=build(1,n+2); cnt=n+2; int k,tot,w; char ch[15]; while(m--){ scanf("%s",ch); if(ch[0]!=‘M‘||ch[2]!=‘X‘) k=read(),tot=read(); if(ch[0]==‘I‘) insert(k,tot); if(ch[0]==‘D‘) eraser(k,tot); if(ch[0]==‘M‘){ if(ch[2]==‘X‘) printf("%d\n",mx[root]); else w=read(),modify(k,tot,w); } if(ch[0]==‘R‘) rever(k,tot); if(ch[0]==‘G‘) push_ans(k,tot); } return 0; }
以上是关于bzoj1500 维修数列的主要内容,如果未能解决你的问题,请参考以下文章