HDU3487 Play With Chain [Splay]

Posted H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU3487 Play With Chain [Splay]相关的知识,希望对你有一定的参考价值。

  题目传送门

题目描述
Problem Description
YaoYao is fond of playing his chains. He has a chain containing n diamonds on it. Diamonds are numbered from 1 to n.
At first, the diamonds on the chain is a sequence: 1, 2, 3, …, n.
He will perform two types of operations:
CUT a b c: He will first cut down the chain from the ath diamond to the bth diamond. And then insert it after the cth diamond on the remaining chain.
For example, if n=8, the chain is: 1 2 3 4 5 6 7 8; We perform “CUT 3 5 4”, Then we first cut down 3 4 5, and the remaining chain would be: 1 2 6 7 8. Then we insert “3 4 5” into the chain before 5th diamond, the chain turns out to be: 1 2 6 7 3 4 5 8.

FLIP a b: We first cut down the chain from the ath diamond to the bth diamond. Then reverse the chain and put them back to the original position.
For example, if we perform “FLIP 2 6” on the chain: 1 2 6 7 3 4 5 8. The chain will turn out to be: 1 4 3 7 6 2 5 8

He wants to know what the chain looks like after perform m operations. Could you help him? 
 
输入格式
Input
There will be multiple test cases in a test data. 
For each test case, the first line contains two numbers: n and m (1≤n, m≤3*100000), indicating the total number of diamonds on the chain and the number of operations respectively.
Then m lines follow, each line contains one operation. The command is like this:
CUT a b c // Means a CUT operation, 1 ≤ a ≤ b ≤ n, 0≤ c ≤ n-(b-a+1).
FLIP a b    // Means a FLIP operation, 1 ≤ a < b ≤ n.
The input ends up with two negative numbers, which should not be processed as a case.
 

 

输出格式
Output
For each test case, you should print a line with n numbers. The ith number is the number of the ith diamond on the chain.
 
样例
Sample Input
8 2 CUT 3 5 4 FLIP 2 6 -1 -1
Sample Output
1 4 3 7 6 2 5 8
 
  分析:
  题目大意就是给你一个数列1,2,3,...n,然后有两种操作,一种是将一段区间取下来再接到另一个位置,另一种是区间反转。
  不难看出这是一道平衡树的题目,题目中的区间反转操作很明显的是Splay,用下放标记的方法很容易实现。再看另一种操作,要求将一段数列截下来然后放入另一段中,这个其实可以旋转以后把要移动的一段直接取下,然后在重新调整平衡树,记录要放入的区间的右端点,再把要放入的区间的左端点作为树根,把截下来的一段直接放上去,再调整,把右端点也接上去就可以了。具体在代码中注释。
 
  Code:
  
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstdlib>
  4 #include<cmath>
  5 #include<iomanip>
  6 #include<iostream>
  7 #include<algorithm>
  8 using namespace std;
  9 const int N=3e5+7;
 10 int n,m,root,tot;
 11 int cnt,ans[N];
 12 struct Node{
 13   int ch[2],val,fa;
 14   int size,mark;
 15   void add(int x,int father){
 16     mark=ch[0]=ch[1]=0;
 17     fa=father;val=x;size=1;}
 18 }t[N];
 19 inline int read()
 20 {
 21   char ch=getchar();int num=0;bool flag=false;
 22   while(ch<0||ch>9){if(ch==-)flag=true;ch=getchar();}
 23   while(ch>=0&&ch<=9){num=num*10+ch-0;ch=getchar();}
 24   return flag?-num:num;
 25 }
 26 inline void pushup(int x)
 27 {
 28   int l=t[x].ch[0],r=t[x].ch[1];
 29   t[x].size=t[l].size+t[r].size+1;
 30 }
 31 inline void pushdown(int x)
 32 {
 33   if(t[x].mark){
 34     t[t[x].ch[0]].mark^=1;
 35     t[t[x].ch[1]].mark^=1;
 36     swap(t[x].ch[0],t[x].ch[1]);
 37     t[x].mark=0;}
 38 }
 39 inline void rotate(int x)
 40 {
 41   int y=t[x].fa;
 42   int z=t[y].fa;
 43   int k=(t[y].ch[1]==x);
 44   t[z].ch[t[z].ch[1]==y]=x;
 45   t[x].fa=z;
 46   t[y].ch[k]=t[x].ch[k^1];
 47   t[t[x].ch[k^1]].fa=y;
 48   t[x].ch[k^1]=y;
 49   t[y].fa=x;
 50   pushup(y);pushup(x);
 51 }
 52 inline void splay(int x,int tag)
 53 {
 54   while(t[x].fa!=tag){
 55     int y=t[x].fa;
 56     int z=t[y].fa;
 57     if(z!=tag)
 58       (t[y].ch[1]==x)^(t[z].ch[1]==y)?
 59     rotate(x):rotate(y);
 60     rotate(x);}
 61   if(tag==0)root=x;
 62 }
 63 inline void insert(int x)
 64 {
 65   int now=root,fa=0;
 66   while(now)
 67     fa=now,now=t[now].ch[x>t[now].val];
 68   now=++tot;
 69   if(fa)t[fa].ch[x>t[fa].val]=now;
 70   t[now].add(x,fa);
 71   splay(now,0);
 72 }
 73 inline int find(int x)
 74 {
 75   int now=root;
 76   while(555){
 77     pushdown(now);
 78     if(t[t[now].ch[0]].size>=x)now=t[now].ch[0];
 79     else if(t[t[now].ch[0]].size+1==x)return now;
 80     else x-=(t[t[now].ch[0]].size+1),now=t[now].ch[1];
 81   }
 82 }
 83 inline int getmax(int x)
 84 {
 85   pushdown(x);
 86   while(t[x].ch[1]){
 87     x=t[x].ch[1];
 88     pushdown(x);}
 89   return x;
 90 }
 91 inline void merge(int x,int y)
 92 {
 93   t[x].ch[1]=y;
 94   t[y].fa=x;
 95 }
 96 inline void flip(int l,int r)
 97 {
 98   l=find(l),r=find(r+2);
 99   splay(l,0);splay(r,l);
100   t[t[t[root].ch[1]].ch[0]].mark^=1;
101 }
102 inline void cut(int x,int y,int z)
103 {
104   int l=find(x),r=find(y+2);
105   splay(l,0);splay(r,l);
106   //找到移动区间的左右端点的位置并调整至根节点
107   int root1=t[t[root].ch[1]].ch[0];
108   t[t[root].ch[1]].ch[0]=0;
109   //将该区间“截”下来
110   pushup(t[root].ch[1]);
111   pushup(root);
112   //调整节点信息
113   int neo=find(z+1);
114   splay(neo,0);
115   //找到放入区间的左端点并调整至根节点
116   int root2=t[root].ch[1];
117   //记录下当前的右端点,因为待会儿合并时会将它直接去掉
118   merge(root,root1);
119   pushup(root);
120   //将截取区间接到当前根节点的右端点
121   int maxx=getmax(root);
122   splay(maxx,0);
123   //找到已经放入的区间的右端点并将其调整至根节点
124   merge(root,root2);
125   pushup(root);
126   //将之前被截取下来的端点和根节点
127 }
128 inline void travel(int now)
129 {
130   pushdown(now);
131   if(t[now].ch[0])travel(t[now].ch[0]);
132   if(t[now].val>1&&t[now].val<n+2)
133     ans[++cnt]=t[now].val-1;
134   if(t[now].ch[1])travel(t[now].ch[1]);
135 }
136 int main()
137 {
138   while(555){
139     n=read();m=read();
140     if(n<0||m<0)break;
141     root=tot=0;
142     for(int i=1;i<=n+2;i++)
143       insert(i);
144     char opt[5];int x,y,z;
145     for(int i=1;i<=m;i++){
146       scanf("%s",opt);
147       if(opt[0]==F){
148     x=read();y=read();
149     flip(x,y);}
150       else{
151     x=read();y=read();z=read();
152     cut(x,y,z);}
153     }
154     cnt=0;
155     travel(root);
156     for(int i=1;i<n;i++)
157       printf("%d ",ans[i]);
158     printf("%d\n",ans[n]);
159   }
160   return 0;

 

以上是关于HDU3487 Play With Chain [Splay]的主要内容,如果未能解决你的问题,请参考以下文章

hdu 3487 Play with Chain (Splay)

HDU 3487:Play with Chain(Splay)

HDU 3487Play with Chain Splay

csu1365 Play with Chain

HDU 3487 Splay tree

hdu1082 Matrix Chain Multiplication