最近看一位大佬狂刷平衡树,怒淦维修数列,自己好久没写splay了,而且也不难,就去做了做。
几下写完了模板,调了调感觉无比正确, 然后交上去无限TLE,以为是写的丑,就一直乱调。
最后发现是回收内存时候的数组忘了清空了,就这东西调了一晚上.....啊啊啊啊啊我要疯啦
题意:需要你维护一个数列的很多种操作: 数字不会超过500000个,操作<=20000,插入的数不超过四百万
题解:splay裸题,瞎维护。整道题其实就只有最后一个问题比较坑。
每个点维护从最左边开始的最大值,从最右边开始的最大值,和中间的最大值,像线段树那样子合并。
代码:
#include<iostream> #include<cstdio> #include<queue> #define MAXN 500000 #define INF 2000000000 using namespace std; inline int read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();} return x*f; } bool rev[MAXN+5],mark[MAXN+5]; int fa[MAXN+5],size[MAXN+5],sum[MAXN+5]; int c[MAXN+5][2],ad[MAXN+5],num[MAXN+5]; queue<int> q;int id[MAXN+5]; int n,m,rt,tot,pos,u,v; char op[50]; struct data{ int l,r,mid; }s[MAXN+5]; void update(int k) { // printf("update%d ",k); int l=c[k][0],r=c[k][1]; sum[k]=sum[l]+sum[r]+num[k]; size[k]=size[l]+size[r]+1; if(!l&&!r){s[k]=(data){num[k],num[k],num[k]};return;} s[k].l=s[k].r=s[k].mid=-INF; if(l){s[k].l=s[l].l;s[k].mid=max(s[k].mid,s[l].mid);} if(r){s[k].r=s[r].r;s[k].mid=max(s[k].mid,s[r].mid);} s[k].l=max(s[k].l,sum[l]+num[k]+(s[r].l>0?s[r].l:0)); s[k].r=max(s[k].r,sum[r]+num[k]+(s[l].r>0?s[l].r:0)); s[k].mid=max(s[k].mid,(s[l].r>0?s[l].r:0)+num[k]+(s[r].l>0?s[r].l:0)); } void pushdown(int k) { // printf("pushdown%d ",k); int l=c[k][0],r=c[k][1]; if(rev[k]) { swap(c[k][0],c[k][1]);swap(s[l].l,s[l].r);swap(s[r].l,s[r].r); rev[k]^=1;rev[l]^=1;rev[r]^=1; update(k); } if(mark[k]) { sum[l]=ad[k]*size[l]; sum[r]=ad[k]*size[r]; mark[k]=0;mark[l]=1;mark[r]=1; ad[l]=ad[r]=num[l]=num[r]=ad[k]; if(ad[k]>0)s[l]=(data){sum[l],sum[l],sum[l]},s[r]=(data){sum[r],sum[r],sum[r]}; else s[l]=(data){ad[k],ad[k],ad[k]},s[r]=(data){ad[k],ad[k],ad[k]}; ad[k]=0; } } void rotate(int x,int &k) { // printf("rotate%d %d ",x,k); int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1; if(y==k) k=x; else c[z][c[z][1]==y]=x; fa[x]=z;fa[y]=x;fa[c[x][r]]=y; c[y][l]=c[x][r];c[x][r]=y; update(y);update(x); } void splay(int x,int&k) { // printf("splay%d %d ",x,k); while(x!=k) { int y=fa[x],z=fa[y]; if(y!=k) { if(c[z][0]==y^c[y][0]==x)rotate(x,k); else rotate(y,k); } rotate(x,k); } } int find(int x,int rk) { // printf("find%d %d ",x,rk); pushdown(x); int l=c[x][0],r=c[x][1]; if(size[l]>=rk)return find(l,rk); if(size[l]+1<rk)return find(r,rk-size[l]-1); return x; } void split(int l,int r) { splay(find(rt,l),rt); splay(find(rt,r),c[rt][1]); } void build(int&x,int l,int r,int last) { if(l>r)return; x=q.front();q.pop();fa[x]=last; int mid=(l+r)>>1; size[x]=1;num[x]=id[mid];rev[x]=mark[x]=ad[x]=0; build(c[x][0],l,mid-1,x); build(c[x][1],mid+1,r,x); update(x); } void init(int&x,int l,int r,int last) { if(l>r)return; x=(l+r)>>1;fa[x]=last; size[x]=1;num[x]=id[x];rev[x]=mark[x]=ad[x]=0; init(c[x][0],l,x-1,x); init(c[x][1],x+1,r,x); update(x); } void reuse(int x) { if(!x)return; if(c[x][0])reuse(c[x][0]); if(c[x][1])reuse(c[x][1]); q.push(x);c[x][0]=c[x][1]=fa[x]=0; } /* void dfs(int x) { printf("%d %d %d %d %d %d %d %d %d %d ",x,fa[x],c[x][0],c[x][1],size[x],num[x],sum[x],s[x].l,s[x].r,s[x].mid); if(c[x][0])dfs(c[x][0]); if(c[x][1])dfs(c[x][1]); } */ int main() { n=read();m=read(); for(int i=1;i<=n;i++)id[i+1]=read(); for(int i=n+3;i<=500002;i++)q.push(i); n+=2;init(rt,1,n,rt); for(int i=1;i<=m;i++) { scanf("%s",op+1); if(op[1]=='I') { pos=read();tot=read();for(int i=1;i<=tot;i++)id[i]=read(); split(pos+1,pos+2);build(c[c[rt][1]][0],1,tot,c[rt][1]); fa[c[c[rt][1]][0]]=c[rt][1];update(c[rt][1]);update(rt);n+=tot; } else if(op[1]=='D') { pos=read();tot=read();split(pos,pos+tot+1); reuse(c[c[rt][1]][0]);c[c[rt][1]][0]=0; update(c[rt][1]);update(rt);n-=tot; } else if(op[1]=='M'&&op[3]=='K') { pos=read();tot=read();u=read();split(pos,pos+tot+1); v=c[c[rt][1]][0];sum[v]=size[v]*u;mark[v]=1;ad[v]=u;num[v]=u; if(u>=0)s[v]=(data){sum[v],sum[v],sum[v]}; else s[v]=(data){u,u,u}; update(c[rt][1]);update(rt); } else if(op[1]=='R') { pos=read();tot=read();split(pos,pos+tot+1); v=c[c[rt][1]][0];rev[v]^=1;swap(s[v].l,s[v].r); update(c[rt][1]);update(rt); } else if(op[1]=='G') { pos=read();tot=read();split(pos,pos+tot+1); printf("%d ",sum[c[c[rt][1]][0]]); } else { split(1,n);u=c[c[rt][1]][0]; printf("%d ",s[u].mid); } // dfs(rt); } return 0; }
啊啊啊啊啊我真的要疯了(不能疯,你还没有写作业)