Play with Chain
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?
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.
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
Source
题意:FLIP操作就是区间的翻转,而CUT则是把某个区间移到某个点后面,本来打算用几次翻转来合成CUT函数,最后没有推出来。so借鉴kuangbin巨巨的作法
1 #include <cstdio> 2 #include <cstdlib> 3 #include <algorithm> 4 using namespace std; 5 const int maxn = 3e5+10; 6 int siz[maxn],pre[maxn],ch[maxn][2],rev[maxn],key[maxn]; 7 int tot,root,n,m; 8 void NewNode(int &r,int father,int k) 9 { 10 r = ++tot; 11 pre[r] = father; 12 ch[r][0] = ch[r][1] = 0; 13 key[r] = k; 14 siz[r] = 1; 15 rev[r] = 0; 16 } 17 void update_rev(int r) 18 { 19 if (!r) 20 return ; 21 swap(ch[r][0],ch[r][1]); 22 rev[r] ^= 1; 23 } 24 void push_up(int r) 25 { 26 siz[r] = siz[ch[r][0]] + siz[ch[r][1]] + 1; 27 } 28 void push_down(int r) 29 { 30 if (rev[r]) 31 { 32 update_rev(ch[r][0]); 33 update_rev(ch[r][1]); 34 rev[r] = 0; 35 } 36 } 37 void build(int &x,int l,int r,int father) 38 { 39 if (l > r) 40 return; 41 int mid = (l + r) >> 1; 42 NewNode(x,father,mid); 43 build(ch[x][0],l,mid-1,x); 44 build(ch[x][1],mid+1,r,x); 45 push_up(x); 46 } 47 void init() 48 { 49 root = tot = 0; 50 NewNode(root,0,-1); 51 NewNode(ch[root][1],root,-1); 52 build(ch[ch[root][1]][0],1,n,ch[root][1]); 53 push_up(ch[root][1]); 54 push_up(root); 55 } 56 57 void Rotate(int x,int kind) 58 { 59 int y = pre[x]; 60 push_down(y); 61 push_down(x); 62 ch[y][!kind] = ch[x][kind]; 63 pre[ch[x][kind]] = y; 64 if (pre[y]) 65 ch[pre[y]][ch[pre[y]][1] == y] = x; 66 pre[x] = pre[y]; 67 ch[x][kind] = y; 68 pre[y] = x; 69 push_up(y); 70 } 71 72 void Splay(int r,int goal) 73 { 74 push_down(r); 75 while (pre[r] != goal) 76 { 77 if (pre[pre[r]] == goal) 78 { 79 push_down(pre[r]); 80 push_down(r); 81 Rotate(r,ch[pre[r]][0] == r); 82 } 83 else 84 { 85 int y = pre[r]; 86 int kind = (ch[pre[y]][1] == y); 87 push_down(pre[y]); 88 push_down(y); 89 push_down(r); 90 if (ch[y][kind] == r) 91 { 92 Rotate(y,!kind); 93 Rotate(r,!kind); 94 } 95 else 96 { 97 Rotate(r,kind); 98 Rotate(r,!kind); 99 } 100 } 101 } 102 push_up(r); 103 if (goal == 0) 104 root = r; 105 } 106 int Get_kth(int r,int k) 107 { 108 push_down(r); 109 int t = siz[ch[r][0]] + 1; 110 if (k == t) 111 return r; 112 if (k >= t) 113 return Get_kth(ch[r][1],k-t); 114 else 115 return Get_kth(ch[r][0],k); 116 } 117 void Reverse(int u,int v) 118 { 119 if (u > v) 120 return; 121 Splay(Get_kth(root,u),0); 122 Splay(Get_kth(root,v+2),root); 123 update_rev(ch[ch[root][1]][0]); 124 push_up(ch[root][1]); 125 push_up(root); 126 } 127 void cut(int x,int y,int z) // cut函数本来想着用几次翻转来实现,推了半天没有推出来。so借鉴kuangbin巨巨的做法 128 { 129 Splay(Get_kth(root,x),0); 130 Splay(Get_kth(root,y+2),root); 131 int tmp = ch[ch[root][1]][0]; 132 ch[ch[root][1]][0] = 0; 133 push_up(ch[root][1]); 134 push_up(root); 135 Splay(Get_kth(root,z+1),0); 136 Splay(Get_kth(root,z+2),root); 137 ch[ch[root][1]][0] = tmp; 138 pre[ch[ch[root][1]][0]] = ch[root][1]; 139 push_up(ch[root][1]); 140 push_up(root); 141 } 142 bool flag; 143 void dfs(int r) 144 { 145 if (!r) 146 return; 147 push_down(r); 148 dfs(ch[r][0]); 149 if (r != -1 && key[r] != -1) 150 { 151 printf(flag ? " %d":"%d",key[r]); 152 flag = 1; 153 } 154 dfs(ch[r][1]); 155 } 156 int main(void) 157 { 158 #ifndef ONLINE_JUDGE 159 freopen("in.txt","r",stdin); 160 #endif 161 while (~scanf ("%d%d",&n,&m)) 162 { 163 if (n < 0 && m < 0) 164 break; 165 init(); 166 for (int i = 0; i < m; i++) 167 { 168 char op[6]; 169 int x,y,z; 170 scanf ("%s",op); 171 if (op[0] == 'C') 172 { 173 scanf ("%d%d%d",&x,&y,&z); 174 cut(x,y,z); 175 } 176 else 177 { 178 scanf ("%d%d",&x,&y); 179 Reverse(x,y); 180 } 181 } 182 flag = 0; 183 dfs(root); 184 printf(" "); 185 } 186 return 0; 187 }