zoukankan      html  css  js  c++  java
  • csu1365 Play with Chain

    很显然的splay,第一次用splay操作区间...我实在佩服这个targan大佬,居然搞出这么牛逼的平衡树,调了大概5个小时终于搞定了。。

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<string>
    #include<set>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<list>
    #include<cmath>
    #include<cstring>
    #include<map>
    #include<stack>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define maxn 300005
    #define ull unsigned long long
    #define ll long long
    #define hashmod 99999839
    #define mod 9997
    struct tree{//splay树
        int sz[2];//以当前结点为根的左右子树大小,不包括当前结点
        int son[2];//当前结点的左右儿子
        int fa;//当前结点的父亲
        int reverse;//翻转标记
        int v;//当前结点表示的权值
    }a[maxn];
    int root;//根节点
    int len;
    int n,m,x,y,z;
    bool f;
    int isrson(int p,int f){
        return a[f].son[1] == p;
    }
    void update(int p){//更新p结点的size
        if(a[p].son[0] != -1) a[p].sz[0] = a[a[p].son[0]].sz[0] + a[a[p].son[0]].sz[1] + 1;
        else a[p].sz[0] = 0;
        if(a[p].son[1] != -1) a[p].sz[1] = a[a[p].son[1]].sz[0] + a[a[p].son[1]].sz[1] + 1;
        else a[p].sz[1] = 0;
    }
    void pushdown(int p){
        swap(a[p].son[0],a[p].son[1]);
        update(p);
        a[p].reverse ^= 1;
        int ls = a[p].son[0],rs = a[p].son[1];
        if(ls != -1) a[ls].reverse ^= 1;
        if(rs != -1) a[rs].reverse ^= 1;
    }
    int find(int x){//找到序列第x个数对应的结点
        int p = root;
        for(;;){
            if(a[p].reverse) pushdown(p);
            if(a[p].sz[0] >= x) p = a[p].son[0];
            else if(a[p].sz[0] + 1 == x) return p;
            else x = x - a[p].sz[0] - 1,p = a[p].son[1];
        }
    }
    void changeson(int p,int f,int v){//把p作为f的v儿子,p,f不一定存在
        if(f != -1) a[f].son[v] = p;
        if(p != -1) a[p].fa = f;
        if(f == -1) root = p;
    }
    void rotate(int p){
        int f = a[p].fa,g = a[f].fa;
        int u = isrson(p,f),v = isrson(f,g);
        changeson(a[p].son[u^1],f,u),changeson(f,p,u^1),changeson(p,g,v);//改变p,f,g的父子关系
        update(f),update(p);
    }
    void splay(int p,int tar){
        if(a[p].fa == tar) return;
        while(a[a[p].fa].fa != tar && a[p].fa != tar){
            int f = a[p].fa,g = a[f].fa;
            int u = isrson(p,f),v = isrson(f,g);
            if(u ^ v) rotate(p),rotate(p);
            else rotate(f),rotate(p);
        }
        if(a[p].fa != tar) rotate(p);
    }
    void getsection(int x,int y){//得到[x,y]区间
        splay(find(x - 1),-1),splay(find(y + 1),root);
    }
    void build(int l,int r){
        len++;
        int p = len;
        int mid = (l + r) >> 1;
        a[p].v = mid,a[p].sz[0] = a[p].sz[1] = 0;
        a[p].son[0] = a[p].son[1] = -1;
        if(l == r) return;
        if(l <= mid - 1) changeson(len + 1,p,0),build(l,mid-1);
        if(mid + 1 <= r) changeson(len + 1,p,1),build(mid+1,r);
        update(p);
    }
    void flip(int x,int y){
        getsection(x,y);//得到区间[x,y]后打标记
        int p = a[a[root].son[1]].son[0];
        a[p].reverse ^= 1;
    }
    void cut(int x,int y,int z){//cut [x,y] z 把区间x,y剪切到z位置后
        //先得到区间[x,y],将其x-1rotate到根,将y+1rotate到根的儿子,则y+1结点的左儿子为根的树即为该区间
        getsection(x,y);
        int p = a[a[root].son[1]].son[0];
        a[a[p].fa].son[0] = -1;
        update(a[p].fa),update(root);
        int t = p;
        p = find(z);
        splay(p,-1),p = find(z + 1),splay(p,root);
        p = a[root].son[1],a[p].son[0] = t,a[t].fa = p;
        update(p),update(root);
    }
    void print(int p){
        if(p == -1) return;
        if(a[p].reverse) pushdown(p),update(p);
        print(a[p].son[0]);
        if(a[p].v != 0 && a[p].v != n + 1)
            if(!f) printf("%d",a[p].v),f = true;
            else printf(" %d",a[p].v);
        print(a[p].son[1]);
    }
    int main(){
        freopen("a.in","r",stdin);
        freopen("b.out","w",stdout);
        char op[10];
        while(~scanf("%d%d",&n,&m)){
            if(n < 0 && m < 0) break;
            len = 0,root = 1,f = false;
            build(0,n+1);
            a[root].fa = -1;
            for(int i = 1;i <= m;++i){
                scanf("%s",op);
                if(op[0] == 'C'){
                    scanf("%d%d%d",&x,&y,&z);
                    ++x,++y,++z;
                    cut(x,y,z);
                    continue;
                }
                scanf("%d%d",&x,&y);
                ++x,++y;
                flip(x,y);
            }
            print(root),putchar('
    ');
        }
        return 0;
    }
  • 相关阅读:
    java基础面试题:说说&和&&的区别
    java基础面试题:java中有没有goto? 在JAVA中如何跳出当前的多重嵌套循环?
    Java基础面试操作题: 获取 1-20 之间的随机数,共计 20 个,要求不能重复 获取 1-20 之间的随机数,共计 10 个,要求不能重
    Intellij设置Eclipse 快捷键
    Intellij 安装sonarlint
    Intellij 关闭参数提示
    Linux中Firefox——Firebug插件安装及使用
    Linux中Firefox——Httpfox插件安装及使用
    OpenCV——Haar-like特征
    Python学习笔记6(列表生成式)
  • 原文地址:https://www.cnblogs.com/zhuiyicc/p/9497552.html
Copyright © 2011-2022 走看看