题解 P4743 【[Wind Festival]Energy Center】

· · 题解

抢到第一篇题解啦

很裸的splay,然而还是没明白为什么出题人把这题排最简单,可能是蒟蒻我想太复杂了

一开始建立splay要加两个哨兵(烧饼)结点1和n+2, 原始的每个设备序列编号加1,令n+=2

新节点编号为++n,将其作为y的左子树,更新y和x维护的值 $D \ x$操作,在splay tree中找到**第x个**结点x旋转到根,找到**第x+2个**结点y旋转到根的右子树 断掉y的左子树 $QA$操作,用一个变量rem记录删掉了多少节点就好,输出n-2-rem $QS\ ll\ rr$操作,在splay tree中找到**第ll个**结点x旋转到根,找到**第rr+2个**结点y旋转到根的右子树,输出y的左子树维护的值 ``` #include<iostream> #include<cmath> #include<algorithm> #include<queue> #include<cstring> #include<cstdio> #include<stack> using namespace std; typedef double dd; int read() { int f=1,x=0; char ss=getchar(); while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();} while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();} return f*x; } const int maxn=30010; int n,m; int a[maxn][210]; int rt,ch[maxn][2],fa[maxn],rem; int val[maxn][210],size[maxn]; void update(int p) { int lc=ch[p][0],rc=ch[p][1]; size[p]=size[lc]+size[rc]+1; for(int i=1;i<=m;++i) val[p][i]=val[lc][i]+val[rc][i]+a[p][i]; } void build(int p,int ll,int rr) { if(ll>rr) return; int mid=ll+rr>>1; fa[mid]=p; size[mid]=1; ch[p][mid>p]=mid; if(ll==rr) { for(int i=1;i<=m;++i)val[ll][i]=a[ll][i]; return; } build(mid,ll,mid-1); build(mid,mid+1,rr); update(mid); } void rotate(int &p,int x) { int y=fa[x],z=fa[y]; int d=(ch[y][0]==x); if(y==p) p=x; else if(ch[z][0]==y) ch[z][0]=x; else ch[z][1]=x; fa[y]=x; fa[ch[x][d]]=y; fa[x]=z; ch[y][d^1]=ch[x][d]; ch[x][d]=y; update(y); update(x); } void splay(int &p,int x) { while(x!=p) { int y=fa[x],z=fa[y]; if(y!=p) { if((ch[z][0]==y)^(ch[y][0]==x))rotate(p,x); else rotate(p,y); } rotate(p,x); } } int find(int p,int k) { int ss=size[ch[p][0]]; if(k==ss+1) return p; else if(k<=ss) return find(ch[p][0],k); else return find(ch[p][1],k-ss-1); } void ins(int k) { int x=find(rt,k+1); splay(rt,x); int y=find(rt,k+2); splay(ch[x][1],y); ch[y][0]=n; fa[n]=y; size[n]=1; for(int i=1;i<=m;++i) val[n][i]=a[n][i]; update(y); update(x); } void del(int k) { int x=find(rt,k); splay(rt,x); int y=find(rt,k+2); splay(ch[x][1],y); fa[ch[y][0]]=0; ch[y][0]=0; update(y); update(x); rem++; } void get(int ll,int rr) { int x=find(rt,ll); splay(rt,x); int y=find(rt,rr+2); splay(ch[x][1],y); for(int i=1;i<=m;++i) printf("%d ",val[ch[y][0]][i]); printf("\n"); } int main() { n=read();m=read(); for(int i=2;i<=n+1;++i) { int k=read(); while(k--) { int x=read()+1,y=read(); a[i][x]=y; } } rt=n+3>>1; build(rt,1,n+2); n+=2; int q=read(); while(q--) { char ss[5]; scanf("%s",&ss); if(ss[0]=='I') { int p=read(),k=read(); ++n; while(k--) { int x=read()+1,y=read(); a[n][x]=y; } ins(p); } else if(ss[0]=='D') del(read()); else if(ss[0]=='Q'&&ss[1]=='A') printf("%d\n",n-2-rem); else if(ss[0]=='Q'&&ss[1]=='S') { int ll=read(),rr=read(); get(ll,rr); } } printf("end"); return 0; //niiick } ```