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.
There is only one case for this problem. The first line contains two integers n and m (1n, m100, 000). Each of the next m lines contains an instruction consisting of two integers a and b (1abn).
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.
10 2 2 5 4 8
1 6 7 3 2 4 5 10 9 8
最开始排列1-N,有M条指令,每条指令(a,b)表示取出第a-b个元素,翻转后添加到排列尾部。
用split操作把a之前的和整个串分开,再把剩下的串分成左边b-a+1个,剩下的在右边,这样就有了left,mid,right,把mid标记旋转,合并left和right,再和mid合并。
旋转就和线段树一样,这里就是swap(ch[0],ch[1]),有标记的话要pushdown。
#include<iostream> #include<cstdio> #include<algorithm> #include<vector> #include<set> #include<utility> #include<cstring> #include<stack> #include<queue> #include<map> #include<deque> #include<cmath> #include<map> #define INF 0x3f3f3f3f #define eps 1e-3 using namespace std; typedef long long LL; const int MAXN=100010; const int MAXM=1030; const int MOD=1000000007; int N,M; struct Node{ Node* ch[2]; int s; int v; int flip; int cmp(int k) const{ int d=k-ch[0]->s; if(d==1) return -1; return d<=0?0:1; } void maintain(){ s=ch[0]->s+ch[1]->s+1; } void pushdown(){ if(flip){ swap(ch[0],ch[1]); ch[0]->flip=!ch[0]->flip; ch[1]->flip=!ch[1]->flip; flip=0; } } }; Node* null=new Node(); void rotate(Node*& o,int d){ Node* k=o->ch[d^1]; o->ch[d^1]=k->ch[d]; k->ch[d]=o; o->maintain(); k->maintain(); o=k; } void splay(Node*& o,int k){ o->pushdown(); int d=o->cmp(k); if(d==1) k-=o->ch[0]->s+1; if(d!=-1){ Node* p=o->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(o,d^1); else rotate(o->ch[d],d); } rotate(o,d^1); } } Node* merge(Node* left,Node* right){ splay(left,left->s); left->ch[1]=right; left->maintain(); return left; } //k>=1 void split(Node* o,int k,Node*& left,Node*& right){ splay(o,k); left=o; right=o->ch[1]; o->ch[1]=null; left->maintain(); } struct SplaySequence{ int n; Node seq[MAXN]; Node* root; Node* build(int sz){ if(!sz) return null; Node* L=build(sz/2); Node* o=&seq[++n]; o->v=n; o->ch[0]=L; o->ch[1]=build(sz-sz/2-1); o->flip=0; o->maintain(); return o; } void init(int sz){ n=0; null->s=0; root=build(sz); } }; vector<int> ans; void print(Node* o){ if(o!=null){ o->pushdown(); print(o->ch[0]); ans.push_back(o->v); print(o->ch[1]); } } SplaySequence ss; int main(){ freopen("in.txt","r",stdin); while(scanf("%d%d",&N,&M)!=EOF){ ss.init(N+1); while(M--){ int a,b; scanf("%d%d",&a,&b); Node *left,*mid,*right,*o; split(ss.root,a,left,o); split(o,b-a+1,mid,right); mid->flip^=1; ss.root=merge(merge(left,right),mid); } print(ss.root); for(int i=1;i<=N;i++) printf("%d\n",ans[i]-1); } return 0; }