UVA 11922 - Permutation Transformer
题意:给一个序列,每次操作选择(a,b),把(a,b)序列翻转之后加到末尾,求最终序列
思路:Splay的应用,多一个flip标记,在开头多一个虚拟的0结点,这样每次就利用Splay进行分裂合并即可
代码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <vector>
using namespace std;
struct SplayTree {
struct Node {
Node *ch[2];
int v, s;
int flip;
Node() {
ch[0] = ch[1] = NULL;
v = s = flip = 0;
}
Node(int v) {
ch[0] = ch[1] = NULL;
this->v = v; s = 1; flip = 0;
}
int cmp(int x) const {
int d = x - 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) {
flip = 0;
swap(ch[0], ch[1]);
ch[0]->flip = !ch[0]->flip;
ch[1]->flip = !ch[1]->flip;
}
}
};
Node *null;
//0 is left, 1 is right
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;
}
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();
}
int findkth(Node *o, int k, int flag) { //1 is bigth, 0 is smallth
if (o == null || k <= 0 || k > o->s) return 0;
int s = (o->ch[flag] == null ? 0 : o->ch[flag]->s);
if (k == s + 1) return o->v;
else if (k <= s) return findkth(o->ch[flag], k, flag);
else return findkth(o->ch[flag^1], k - s - 1, flag);
}
void removetree(Node* &x) {
if (x == NULL) return;
if (x->ch[0] != NULL) removetree(x->ch[0]);
if (x->ch[1] != NULL) removetree(x->ch[1]);
delete x; x = NULL;
}
void init() {
removetree(root);
null = new Node();
}
void build(Node* &o, int l, int r) {
if (l > r) {
o = null;
return;
}
int mid = (l + r) / 2;
o = new Node(mid);
build(o->ch[0], l, mid - 1);
build(o->ch[1], mid + 1, r);
o->maintain();
}
int n, m;
Node *root;
void print(Node* &o) {
if (o != null) {
o->pushdown();
print(o->ch[0]);
if (o->v >= 1)
printf("%d\n", o->v);
print(o->ch[1]);
}
}
void solve() {
init();
build(root, 0, n);
int a, b;
while (m--) {
scanf("%d%d", &a, &b);
Node *left, *mid, *right, *o;
split(root, a, left, o);
split(o, b - a + 1, mid, right);
mid->flip ^= 1;
root = merge(merge(left, right), mid);
}
print(root);
}
} gao;
int main() {
while (~scanf("%d%d", &gao.n, &gao.m)) {
gao.solve();
}
return 0;
}