UVA11922 Permutation Transformer(Spaly / Treap)

题源

题意:
             1 1 n的序列,每次操作给出 [l,r] [ l , r ] ,对 [l,r] [ l , r ] 的元素反转后加到序列末尾,输出最终序列。

思路:
             Splay S p l a y 维护也可以, 做合并和分裂的 Treap T r e a p 模板。

#include<bits/stdc++.h>
typedef long long ll;
const int maxn = 1e3 + 10;
const int maxnode = 1e5 + 10;
using namespace std;

int root, treapcnt, key[maxnode], pr[maxnode];
int ch[maxnode][2], sz[maxnode];
int lazy[maxnode];

void init() {
    root = 0; treapcnt = 1;
    sz[0] = 0; lazy[0] = 0;
}

void update(int x) { sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1; } ///maintain 操作
void _rotate(int &x, int t) {
    int y = ch[x][t ^ 1];
    ch[x][t ^ 1] = ch[y][t];
    ch[y][t] = x;
    update(x); update(y);
    x = y;
}

void push_down(int o) {
    if(!lazy[o]) return ;
    int &ls = ch[o][0], &rs = ch[o][1];
    swap(ls, rs);
    lazy[ls] ^= 1; lazy[rs] ^= 1;
    lazy[o] = 0;
}

void __insert(int &x, int k) {
    if(x) {
        int t = key[x] < k;
        __insert(ch[x][t], k);
        if(pr[ch[x][t]] < pr[x]) _rotate(x, t ^ 1);
    } else {  ///申请新节点
        x = treapcnt++;
        key[x] = k;
        pr[x] = rand();
        ch[x][0] = ch[x][1] = 0;
        lazy[x] = 0;
    }
    update(x);
}

int __getKth(int &x, int k) {
    push_down(x);
    int siz = sz[ch[x][0]];
    if(k <= siz) return __getKth(ch[x][0], k);
    k -= 1 + siz;
    if(k <= 0) return key[x];
    return __getKth(ch[x][1], k);
}

int __Merge(int &a, int &b) { ///合并a 和 b
    push_down(a); push_down(b);
    if(!a) return b;
    if(!b) return a;
    if(key[a] < key[b]) {
        ch[a][1] = __Merge(ch[a][1], b);
        update(a); return a;
    } else {
        ch[b][0] = __Merge(a, ch[b][0]);
        update(b); return b;
    }
}

typedef pair<int, int> pa;
pa __Split(int &o, int k) { ///前k小在第一个根节点
    pa d(0, 0);
    if(!o) return d;
    push_down(o);
    if(k <= sz[ch[o][0]]) {
        d = __Split(ch[o][0], k);
        ch[o][0] = d.second;
        update(o); d.second = o;
    } else {
        d = __Split(ch[o][1], k - sz[ch[o][0]] - 1);
        ch[o][1] = d.first;
        update(o); d.first = o;
    }
    return d;
}

void solve(int l, int r) {
    pa rt = __Split(root, r);
    pa lt = __Split(rt.first, l - 1);
    root = __Merge(lt.first, rt.second);
    lazy[lt.second] ^= 1;
    root = __Merge(root, lt.second);
}

int n, m, T, kase = 1;

int main() {
    while(scanf("%d %d", &n, &m) != EOF) {
        init();
        for(int i = 1; i <= n; i++) __insert(root, i);
        while(m--) {
            int l, r; scanf("%d %d", &l, &r);
            solve(l, r);
        }
        for(int i = 1; i <= n; i++) {
            int ans = __getKth(root, i);
            printf("%d\n", ans);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值