Time Limit: 2000MS | Memory Limit: Unknown | 64bit IO Format: %lld & %llu |
Description

Permutation Transformer
Permutation Transformer |
Write a program to transform the permutation 1, 2, 3,..., n according to m instructions. Each instruction (a, b) means to take out the subsequence from the a-th to the b-th element, reverse it, then append it to the end.
Input
There is only one case for this problem. The first line contains two integers n and m ( 1n, m
100, 000). Each of the next m lines contains an instruction consisting of two integers a and b ( 1
a
b
n).
Output
Print n lines, one for each integer, the final permutation.
Explanation of the sample below
Instruction (2,5): Take out the subsequence {2,3,4,5}, reverse it to {5,4,3,2}, append it to the remaining permutation {1,6,7,8,9,10}
Instruction (4,8): The subsequence from the 4-th to the 8-th element of {1,6,7,8,9,10,5,4,3,2} is {8,9,10,5,4}. Take it out, reverse it, and you'll get the sample output.
Warning: Don't use cin, cout for this problem, use faster i/o methods e.g scanf, printf.
Sample Input
10 2 2 5 4 8
Sample Output
1 6 7 3 2 4 5 10 9 8
解决方案:数列的拆分与合并可用splay树来模拟,翻转可根据之前线段树的经验,用一个标记来完成,写了个filp标记和push_down函数
code:#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<vector> using namespace std; struct node { node *ch[2]; int v; int s; int flip; int cmp(int k)const { int d=k - ch[0]->s; if(d==1) return -1; return d<=0?0:1; }///比较函数 void pushdown() { if(flip) { flip=0; swap(ch[0],ch[1]); ch[0]->flip=!ch[0]->flip; ch[1]->flip=!ch[1]->flip; } }///翻转函数 void maintian() { s=ch[0]->s+ch[1]->s+1; }///统计子孙函数 }; node *null=new node(); void rotate(node * &rt,int d) { node *k=rt->ch[d^1]; rt->ch[d^1]=k->ch[d]; k->ch[d]=rt; rt->maintian(); k->maintian(); rt=k; }///翻滚函数 void splay(node * &rt,int k) { rt->pushdown(); int d=rt->cmp(k); if(d==1) k-=rt->ch[0]->s+1; if(d!=-1) { node *p=rt->ch[d]; p->pushdown(); int d2=p->cmp(k); int k2=(d2==0?k:k-p->ch[0]->s-1); if(d2!=-1) { splay(p->ch[d2],k2); if(d==d2) rotate(rt,d^1); else rotate(rt->ch[d],d); } rotate(rt,d^1); } }///伸展函数 node * merge(node *left,node *right) { splay(left,left->s); left->ch[1]=right; left->maintian(); return left; }///合并 void split(node * rt,int k,node * & left,node * & right) { splay(rt,k); left=rt; right=rt->ch[1]; rt->ch[1]=null; left->maintian(); }///拆分 const int maxn=101000; struct splayqueue { int n; node seq[maxn]; node *root; node *build(int sz) { if(!sz) return null; node *L=build(sz/2); node *rt=&seq[++n]; rt->v=n; rt->ch[0]=L; rt->ch[1]=build(sz-sz/2-1); rt->flip=rt->s=0; rt->maintian(); return rt; } void init(int sz) { null->s=0; n=0; root=build(sz); } }; vector<int>V; void print(node *rt){ if(rt!=null){ rt->pushdown(); print(rt->ch[0]); V.push_back(rt->v); print(rt->ch[1]); } } splayqueue ss; int main() { int n,m; scanf("%d%d",&n,&m); V.clear(); ss.init(n+1); // cout<<"sd"; while(m--){ int a,b; scanf("%d%d",&a,&b); node *left,*mid,*right,*rt; split(ss.root,a,left,rt);///最左那个点事虚拟节点 split(rt,b-a+1,mid,right); mid->flip^=1; ss.root=merge(merge(left,right),mid); } print(ss.root); for(int i=1;i<V.size();i++){ printf("%d\n",V[i]-1); } return 0; }