题目链接:https://vjudge.net/problem/Gym-247729C
题意:长度为 n 的一叠牌,从上往下编号为 1 - n,然后 m 次操作,每次把从 a 开始往下数 b 张牌(包括 a)放到整叠牌的最上面,m 次操作之后,输出从上往下每张牌的编号。
Input
第一行输入 n 和 m,1 ≤ n, m ≤ 1e5,然后 m 行,每行两个数 a , b,表示从 a 开始往下数 b 张牌(包括 a)放到整叠牌的最上面。
Output
输出从上往下每张牌的编号。
Sample Input
5 3
2 3
1 4
2 4
Sample Output
3 4 1 5 2
思路:假设我们要把 a 这个区间放到最前面,那么我们可以先翻转 a 区间,再翻转 b 区间,最后翻转 c 区间就可以实现了,然后就可以用 splay 去做这道题。
splay学习:https://www.cnblogs.com/lsl127/p/12884891.html
#include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #define inf 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 100010; struct node { int data; int lazy; int cnt, siz; int fa, son[2]; } tree[N]; int n, m; int root, totnode; int a[N]; int ans[N], top; int get_side(int num) { int fa = tree[num].fa; return tree[fa].son[1] == num; } void update(int num) { if(num == 0) return ; int l = tree[num].son[0]; int r = tree[num].son[1]; tree[num].siz = tree[num].cnt; if(l) tree[num].siz += tree[l].siz; if(r) tree[num].siz += tree[r].siz; } void Rotate(int c) { int b = tree[c].fa; int a = tree[b].fa; int w = get_side(c); int w2 = get_side(b); int d = tree[c].son[w ^ 1]; tree[b].son[w] = d; tree[d].fa = b; tree[c].son[w ^ 1] = b; tree[c].fa = a; tree[b].fa = c; if(a) { tree[a].son[w2] = c; } update(b); update(c); } void splay(int c, int tar) { while(tree[c].fa != tar) { int b = tree[c].fa; int a = tree[b].fa; if(a != tar) { if(get_side(c) == get_side(b)) Rotate(b); else Rotate(c); } Rotate(c); } if(tar == 0) root = c; } void pushdown(int num) { tree[num].lazy = 0; int l = tree[num].son[0]; int r = tree[num].son[1]; tree[l].lazy ^= 1; tree[r].lazy ^= 1; int tmp = l; tree[num].son[0] = r; tree[num].son[1] = tmp; } int Find(int x) { int pos = root; while(1) { if(tree[pos].lazy) pushdown(pos); int l = tree[pos].son[0]; int r = tree[pos].son[1]; int lsiz = tree[l].siz; if(l && lsiz >= x) pos = l; else { int tmp = tree[pos].cnt; if(l) tmp += tree[l].siz; if(x <= tmp) return pos; x -= (tmp); pos = r; } } } void get_ans(int now) { if(tree[now].lazy) pushdown(now); int l = tree[now].son[0]; int r = tree[now].son[1]; if(l) get_ans(l); if(tree[now].data != -inf && tree[now].data != inf) ans[top++] = tree[now].data; if(r) get_ans(r); } void Reverse(int l, int r) { splay(Find(l - 1), 0); splay(Find(r + 1), root); int now = tree[tree[root].son[1]].son[0]; tree[now].lazy ^= 1; } void print() { // cout << top << endl; for(int i = 0; i < top; i++) { if(i == top - 1) printf("%d\n", ans[i]); else printf("%d ", ans[i]); } return ; } void fun(int x, int y) { int l = x + 1; int r = x + y; Reverse(l, r); Reverse(2, l - 1); Reverse(2, r); } int build(int l, int r, int fa) { if(l > r) return 0; int now = ++totnode; int mid = (l + r) / 2; tree[now].data = a[mid]; tree[now].fa = fa; tree[now].lazy = 0; tree[now].cnt = 1; tree[now].son[0] = build(l, mid - 1, now); tree[now].son[1] = build(mid + 1, r, now); update(now); return now; } int main() { int x, y; scanf("%d %d", &n, &m); n += 2; a[1] = -inf; a[n] = inf; for(int i = 2; i < n; i++) a[i] = i - 1; root = build(1, n, 0); for(int i = 1; i <= m; i++) { scanf("%d %d", &x, &y); fun(x, y); } top = 0; get_ans(root); print(); return 0; }