Splay模板
题目:https://www.luogu.org/problemnew/show/P3391
主要练习翻转操作;
有好几个地方的顺序写反了,调了好久好久...
整体+1,就可以在翻转时使用左端点-1和右端点+1了;
节点的val是在原数列中的位置,节点所在的树中位置是现在数列的顺序;
所以输出就是中序遍历,输出val。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int const MAXN=1e5+5; int n,m,cnt,root,del_cur,del_pool[MAXN]; struct N{ int ch[3],fa,val,rev,size; }t[MAXN]; int newnode() { if(del_cur) { int x=del_cur;del_cur--; return del_pool[x]; } cnt++; return cnt; } void del(int x) { del_pool[++del_cur]=x; t[x].ch[0]=0;t[x].ch[1]=0;t[x].fa=0;t[x].val=0; t[x].rev=0;t[x].size=0; } void pushup(int x) { t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1; } void pushdown(int x) { if(t[x].rev) { t[t[x].ch[0]].rev^=1; t[t[x].ch[1]].rev^=1; swap(t[x].ch[0],t[x].ch[1]);//(顺序) t[x].rev=0; } } void rotate(int x) { int y=t[x].fa,z=t[y].fa; int d=t[y].ch[1]==x; t[z].ch[t[z].ch[1]==y]=x;t[x].fa=z; t[y].ch[d]=t[x].ch[d^1];t[t[x].ch[d^1]].fa=y; t[x].ch[d^1]=y;t[y].fa=x;//与上行顺序不能反 pushup(y);pushup(x);//顺序 } void splay(int x,int goal) { while(t[x].fa!=goal)//while而非if { int y=t[x].fa,z=t[y].fa; if(z!=goal) { if((t[y].ch[0]==x)==(t[z].ch[0]==y))rotate(y); else rotate(x); } rotate(x); } pushup(x); if(!goal)root=x; } void insert(int v) { if(!root) { root=newnode(); t[root].val=v;t[root].size=1; return; } int x=root; while(1) { int d=t[x].val<v; if(!t[x].ch[d]) { int k=newnode(); t[x].ch[d]=k;t[k].fa=x; t[k].val=v;t[k].size=1; splay(k,0);//! break; } x=t[x].ch[d]; } } int Kth(int k) { int u=root; while(1) { pushdown(u); if(t[t[u].ch[0]].size+1==k)return u; if(t[t[u].ch[0]].size+1>k)u=t[u].ch[0]; else { k-=t[t[u].ch[0]].size+1; u=t[u].ch[1];//与上行顺序不能反 } } } void Rev(int L,int R) { int l=Kth(L),r=Kth(R+2); splay(l,0);splay(r,l);//r,l而非l,r t[t[r].ch[0]].rev^=1; } void print(int x) { pushdown(x); // printf("x=%d l=%d r=%d\n",x,t[x].ch[0],t[x].ch[1]); if(t[x].ch[0])print(t[x].ch[0]); if(t[x].val>1&&t[x].val<=n+1)printf("%d ",t[x].val-1); if(t[x].ch[1])print(t[x].ch[1]); } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n+2;i++)insert(i);//+1 for(int i=1,l,r;i<=m;i++) { scanf("%d%d",&l,&r); Rev(l,r); } print(root); return 0; }