题目背景
这是一道经典的Splay模板题——文艺平衡树。
题目描述
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
输入格式
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,⋯n−1,n) m表示翻转操作次数
接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq n1≤l≤r≤n
输出格式
输出一行n个数字,表示原始序列经过m次变换后的结果
输入输出样例
输入 #15 3 1 3 1 3 1 4输出 #1
4 3 2 1 5
这题搞了好久 把权值平衡树和区间平衡树搞混了
这题看似翻转了 其BST性质被破坏了 其实没有 下标仍然保持BST性质 只是val交换了
在最左和右分别插入一个值 方便维护
翻转时
l=kth(l);r=kth(r+2); 那么根结点的右儿子的左子树就是序列 l-r
#include<bits/stdc++.h> using namespace std; //input by bxd #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define pb push_back #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) typedef pair<int,int>pii; ////////////////////////////////// const int N=2e6+10; int son[N][2],fa[N],siz[N],cnt[N],val[N],ncnt,root,col[N],n,m; int chk(int x) { return son[fa[x]][1]==x; } void up(int x) { siz[x]=siz[son[x][1]]+siz[son[x][0]]+cnt[x]; } void down(int x) { if(col[x]) { col[son[x][0]]^=1; col[son[x][1]]^=1; col[x]=0; swap(son[x][0],son[x][1]); } } void rotate(int x) { int y=fa[x],z=fa[y],k=chk(x),w=son[x][k^1]; son[y][k]=w;fa[w]=y; son[z][chk(y)]=x;fa[x]=z; son[x][k^1]=y;fa[y]=x; up(x);up(y); } void splay(int x,int goal=0) { while(fa[x]!=goal) { int y=fa[x],z=fa[y]; if(z!=goal) { if(chk(y)==chk(x))rotate(y); else rotate(x); } rotate(x); } if(!goal)root=x; } void insert(int x) { int pos=root,p=0; while(pos&&val[pos]!=x)p=pos,pos=son[pos][x>val[pos]]; if(pos)cnt[pos]++; else { pos=++ncnt; if(p)son[p][x>val[p]]=pos; son[pos][0]=son[pos][1]=0; cnt[pos]=siz[pos]=1; val[pos]=x;fa[pos]=p; } splay(pos); } int kth(int k) { int pos=root; while(1) { down(pos); if(son[pos][0]&&siz[son[pos][0]]>=k)pos=son[pos][0]; else if(k>siz[son[pos][0]]+cnt[pos])k-=siz[son[pos][0]]+cnt[pos],pos=son[pos][1]; else {splay(pos);return pos;} } } void output(int x) { down(x); if(son[x][0])output(son[x][0]); if(val[x]>1&&val[x]<n+2)printf("%d ",val[x]-1); if(son[x][1])output(son[x][1]); } void work(int l,int r) { // printf("aaa"); l=kth(l);r=kth(r+2); // printf("vall=%d valr=%d\n",val[l],val[r]); splay(l);splay(r,l); col[son[son[root][1]][0]]^=1; } int main() { scanf("%d%d",&n,&m); rep(i,1,n+2)insert(i); while(m--) { int l,r;scanf("%d%d",&l,&r); work(l,r); } output(root); }View Code