您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n
输出一行n个数字,表示原始序列经过m次变换后的结果
N,M<=100000
平衡树
splay区间反转裸题。
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <cstdlib> #include <cmath> #define maxn 1500000 using namespace std; int n,m,tot=0,root=0; struct splay { int data,l,r,fa,rev,size; }a[maxn]; void Push_up(int x) { a[x].size=a[a[x].l].size+a[a[x].r].size+1; } void Push_down(int x) { if (a[x].rev) { a[x].rev=0; swap(a[x].l,a[x].r); a[a[x].l].rev^=1; a[a[x].r].rev^=1; } } void New_Node(int &x,int fa,int key) { x=++tot; a[x].fa=fa; a[x].l=a[x].r=a[x].rev=0; a[x].data=key; } void Build(int &x,int fa,int l,int r) { if (l>r) return; int m=(l+r)>>1; New_Node(x,fa,m-1); Build(a[x].l,x,l,m-1); Build(a[x].r,x,m+1,r); Push_up(x); } void zig(int x) { int y=a[x].fa; int z=a[y].fa; Push_down(y),Push_down(x); a[y].fa=x,a[x].fa=z; a[y].l=a[x].r,a[a[x].r].fa=y,a[x].r=y; if (y==a[z].l) a[z].l=x; else a[z].r=x; Push_up(y); } void zag(int x) { int y=a[x].fa; int z=a[y].fa; Push_down(y),Push_down(x); a[y].fa=x,a[x].fa=z; a[y].r=a[x].l,a[a[x].l].fa=y,a[x].l=y; if (a[z].l==y) a[z].l=x; else a[z].r=x; Push_up(y); } void splay(int x,int s) { Push_down(x); while (a[x].fa!=s) { int y=a[x].fa; int z=a[y].fa; if (z==s) { if (x==a[y].l) zig(x); else zag(x); break; } if (y==a[z].l) { if (x==a[y].l) zig(y),zig(x); else zag(x),zig(x); } else { if (x==a[y].r) zag(y),zag(x); else zig(x),zag(x); } } Push_up(x); if (s==0) root=x; } int Findkth(int x,int k) { Push_down(x); int s=a[a[x].l].size; if (k==s+1) return x; if (k<=s) return Findkth(a[x].l,k); return Findkth(a[x].r,k-s-1); } void reserve(int l,int r) { int x=Findkth(root,l),y=Findkth(root,r+2); splay(x,0); splay(y,root); a[a[y].l].rev^=1; } void dg(int x) { if (!a[x].l&&!a[x].r) { if (a[x].data>0&&a[x].data<=n) printf("%d ",a[x].data); return; } Push_down(x); if (a[x].l) dg(a[x].l); if (a[x].data>=1&&a[x].data<=n) printf("%d ",a[x].data); if (a[x].r) dg(a[x].r); } void print() { dg(root); cout<<endl; } int main() { scanf("%d%d",&n,&m); Build(root,0,1,n+2); while (m--) { int l,r; scanf("%d%d",&l,&r); reserve(l,r); } print(); return 0; }
小结:
1.TLE是因为Findkth的时候忘记先Push_down(x)