2018牛客多校第三场 C.Shuffle Cards

题意:

  给出一段序列,每次将从第p个数开始的s个数移到最前面。求最终的序列是什么。

题解:

  Splay翻转模板题。存下板子。

#include <bits/stdc++.h>
using namespace std;
const int INF = 1e6;
const int N = 1e5+10;
int n, m;
int s, t;
int root, sz, tot;
int key[N], f[N], size[N], delta[N], cnt[N], ch[N][2];
int a[N], ans[N];
int get(int x) {
    return ch[f[x]][1] == x;
}
void update(int x) {
    if(x) {
        size[x] = cnt[x];
        if(ch[x][0]) size[x] += size[ch[x][0]];
        if(ch[x][1]) size[x] += size[ch[x][1]];
    }
}
int build(int l, int r, int fa) {
    if (l > r) return 0;
    int mid = l+r>>1;
    int now = ++sz;
    key[now] = a[mid]; f[now] = fa; cnt[now] = 1;
    int lch = build(l, mid-1, now);
    int rch = build(mid+1, r, now);
    ch[now][0] = lch, ch[now][1] = rch;
    update(now);
    return now;
}
void pushdown(int x) {
    if(x && delta[x]) {
        swap(ch[x][0], ch[x][1]);
        delta[ch[x][0]] ^= 1; delta[ch[x][1]] ^= 1;
        delta[x] = 0;
    }
}
void rotate(int x) {
    pushdown(f[x]);
    pushdown(x);
    int old = f[x], oldf = f[old], which = get(x);
    ch[old][which] = ch[x][which^1]; f[ch[old][which]] = old;
    f[old] = x; ch[x][which^1] = old;
    f[x] = oldf;
    if(oldf) ch[oldf][ch[oldf][1]==old] = x;
    update(old); update(x);
}
void splay(int x, int tar) {
    for(int fa; (fa = f[x])!=tar; rotate(x))
        if(f[fa] != tar)
            rotate((get(x)==get(fa))?fa:x);
    if(!tar) root = x;
}
int find(int x) {
    int now = root, fa = 0;
    while(1) {
        pushdown(now);
        if(x <= size[ch[now][0]])
            now = ch[now][0];
        else {
            x -= size[ch[now][0]]+1;
            if(x == 0) return now;
            now = ch[now][1];
        }
    }
}
void print(int now) {
    pushdown(now);
    if(ch[now][0]) print(ch[now][0]);
    if(key[now]!=-INF && key[now]!=INF) ans[++tot] = key[now];
    if(ch[now][1]) print(ch[now][1]);
}
int main() {
    scanf("%d%d", &n, &m);
    a[1] = -INF; a[n+2] = INF;
    for(int i = 2; i <= n+1; i++) a[i] = i-1;
    root = build(1, n+2, 0);
    while(m--) {
        scanf("%d%d", &s, &t);
        if(s == 1) continue;
        int f1 = find(1);
        int f2 = find(s+t+1);
        splay(f1, 0);
        splay(f2, f1);
        delta[ch[ch[root][1]][0]] ^= 1;
        f2 = find(t+2);
        splay(f2, f1);
        delta[ch[ch[root][1]][0]] ^= 1;
        f1 = find(t+1);
        f2 = find(s+t+1);
        splay(f1, 0);
        splay(f2, f1);
        delta[ch[ch[root][1]][0]]^=1;
    }
    print(root);
    for(int i = 1; i < n; i++) printf("%d ", ans[i]);
    printf("%d\n", ans[n]);
}
View Code

 

posted @ 2018-07-28 09:46  Pneuis  阅读(236)  评论(0编辑  收藏  举报