uva 11922 Permutation Transformer(Splay tree,懒标记传递)

来源:互联网 发布:淘宝网上开店实战入门 编辑:程序博客网 时间:2024/04/28 20:40

wiki

http://zh.wikipedia.org/wiki/%E4%BC%B8%E5%B1%95%E6%A0%91

关于Splay tree效率分析(包括三种旋转方式图解):

http://www.cs.waikato.ac.nz/Teaching/COMP317B/Week_6/Splay_tree.html

注意,Splay tree的三种旋转中,x的父节点不是root且三点不同线的情况,是在祖父节点做两次同样的旋转。


取出一段区间放到末尾,直接用splay tree可以完成。要做翻转则用到lazy mark。预处理要先加一个虚拟节点,否则a=1时,不满足split的参数要求。

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <vector>#include <queue>#include <stack>#include <cassert>#include <algorithm>#include <cmath>#include <set>#include <limits>using namespace std;#define MIN(a, b) ((a) < (b) ? (a) : (b))#define MAX(a, b) ((a) > (b) ? (a) : (b))#define REP(i, s, t) for(int (i)=(s);(i)<=(t);++(i))#define UREP(i, s, t) for(int (i)=(s);(i)>=(t);--(i))#define REPOK(i, s, t, o) for(int (i)=(s);(i)<=(t) && (o);++(i))#define MAXN 100#define MAXM 10000#define MOD 10000007#define PI 3.1415926535897932384626433832795#define HALF_PI 1.5707963267948966192313216916398typedef long long LL;const double maxdouble = numeric_limits<double>::max();const double eps = 1e-10;const int INF = 0x7FFFFFFF;// Splay Tree 伸展树// 把一棵Splay tree看作一段区间 其中每一棵子树都是一段小区间// 不一定要满足BST的性质 可以维护一种顺序关系 例如让某段区间翻转// 可以加上lazy marktypedef struct Node {    Node *ch[2];    int v;  // value    int s;  // size 名次树中子树结点个数    int flip;    int cmp(int k) const {        int d = k - 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;        }    }}SplayTreeNode;const int maxnode = 100000 + 10;SplayTreeNode nullSpace; // null指向的内存SplayTreeNode* null = &nullSpace;struct SplayTree {    int n;    // seq 是预先分配的储存节点的空间 这样不用动态申请    SplayTreeNode seq[maxnode+5];    SplayTreeNode* root;    void rotate(SplayTreeNode* &o, int d) {        SplayTreeNode* k = o->ch[d^1];        o->ch[d^1] = k->ch[d];        k->ch[d] = o;        o->maintain();        k->maintain();        o = k;    }    void splay(SplayTreeNode* &o, int k) {        o->pushdown();        int d = o->cmp(k);        if (d == 1) k -= o->ch[0]->s + 1;        if (d != -1) {            SplayTreeNode* 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);        }    }    // 合并两棵splay tree    // 先将第一棵树的最大节点伸展 结果是根节点没有右子树    // left不能为null    SplayTreeNode* merge(SplayTreeNode* &left, SplayTreeNode* &right) {        splay(left, left->s);        left->ch[1] = right;        left->maintain();        return left;    }    // 把o的前k小结点放在left里,其他的放在right里。    // !!!1<=k<=o->s。当k=o->s时,right=null    void split(SplayTreeNode* o, int k, SplayTreeNode* &left, SplayTreeNode* &right) {        splay(o, k);        left = o;        right = o->ch[1];        if (o->ch[1] != null)            o->ch[1] = null;        left->maintain();    }    Node* build(int sz) {        if (!sz) return null;        Node* L = build(sz/2);        Node* o = &seq[++n];        o->v = n;        o->ch[0] = L;        o->ch[1] = build(sz - sz/2 - 1);        o->flip = o->s = 0;        o->maintain();        return o;    }    void init(int sz) {        n = 0;        null->s = 0;        root = build(sz);    }};SplayTree tree;void print(SplayTreeNode* o) {    if (o->flip)        o->pushdown();    if (o->ch[0] != null) print(o->ch[0]);    if (o->v != 1)        printf("%d\n",o->v-1);    if (o->ch[1] != null) print(o->ch[1]);}void debug(SplayTreeNode *x) {    printf("\n---debug----\n");    print(x);    printf("---debug----\n");}int main() {    freopen("input.in", "r", stdin);    int n, m;    scanf("%d%d",&n,&m);    tree.init(n+1);    //debug();    int a, b;    SplayTreeNode *first, *second, *third;    REP(i, 1, m) {        scanf("%d%d",&a,&b);        tree.split(tree.root, a, first, second);        tree.split(second, b - a + 1, second, third);        second->flip = !second->flip;        if (third != null) {            tree.merge(third, second);            tree.merge(first, third);        } else {            tree.merge(first, second);        }        //debug(third);        tree.root = first;        //debug(tree.root);    }    print(tree.root);    return 0;}


0 0
原创粉丝点击