• 文艺平衡树 lg3391(splay维护区间入门)


    splay是支持区间操作的,先做这道题入个门

    大多数操作都和普通splay一样,就不多解释了,只解释一下不大一样的操作

    #include<bits/stdc++.h>
    using namespace std;
    #define INF 0x3f3f3f3f
    inline int read(){
        int w=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9'){
            if(ch=='-') f=-1;
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            w=(w<<3)+(w<<1)+ch-48;
            ch=getchar(); 
        }
        return w*f;
    }
    int n,m,tot,cnt,root;
    struct node{
        int ch[2],sum,cnt,val,f,rev;//比普通平衡树多一个lazy tag
    }st[1000010];
    inline void push_up(int p){
        st[p].sum=st[st[p].ch[0]].sum+st[st[p].ch[1]].sum+st[p].cnt;
    }
    inline bool identify(int p){
        return st[st[p].f].ch[1]==p;
    }
    inline void connect(int x,int fa,int son){
        st[x].f=fa;st[fa].ch[son]=x;return;
    }
    inline void rotate(int x){
        int y=st[x].f;int z=st[y].f;
        int yson=identify(x);int zson=identify(y);
        int b=st[x].ch[yson^1];
        connect(b,y,yson);connect(y,x,(yson^1));connect(x,z,zson);
        push_up(y);push_up(x);return;
    }
    inline void splay(int x,int goal){
        while(st[x].f!=goal){
            int y=st[x].f;int z=st[y].f;
            int yson=identify(x);int zson=identify(y);
            if(z!=goal){
                if(yson==zson) rotate(y);
                else rotate(x);
            }
            rotate(x);
        }
        if(!goal) root=x;
        return;
    }
    inline void insert(int x){
        int now=root;int f=0;
        while(st[now].val!=x&&now){
            f=now;
            now=st[now].ch[x>st[now].val];
        }
        if(now){
            st[now].cnt++;
        }
        else{
            tot++;now=tot;
            if(f){
                st[f].ch[x>st[f].val]=now;
            }
            st[now].ch[0]=st[now].ch[1]=0;
            st[now].cnt=st[now].sum=1;
            st[now].val=x;st[now].f=f;
        }
        splay(now,0);return;
    }
    inline void push_down(int p){
        int ls=st[p].ch[0];int rs=st[p].ch[1];
        if(st[p].rev){
            swap(st[p].ch[0],st[p].ch[1]);
            st[st[p].ch[0]].rev^=1;
            st[st[p].ch[1]].rev^=1;
            st[p].rev=0;
        }
    }
    inline void find(int x){
        int now=root;if(!now) return;
        while(st[now].val!=x&&st[now].ch[x>st[now].val]){
            now=st[now].ch[x>st[now].val];
        }
        splay(now,0);return;
    }
    inline int Next(int x,int f){
        find(x);int now=root;
        if(st[now].val<x&&!x) return now;
        if(st[now].val>x&&x) return now;
        now=st[now].ch[f];
        while(st[now].ch[f^1]) now=st[now].ch[f^1];
        return now;
    }
    inline int k_th(int x){
        int now=root;
        if(st[now].sum<x) return false;
        while(true){
            push_down(now);//在查找的时候记得下移标记
            int ls=st[now].ch[0];
            if(x>st[ls].sum+st[now].cnt){
                x-=st[ls].sum+st[now].cnt;
                now=st[now].ch[1];
            }
            else if(x<=st[ls].sum){
                now=ls;
            }
            else return now;//这个地方把返回原值改成返回位置
        }
    }inline void rev(int l,int r){
        int x=k_th(l-1);int y=k_th(r+1);
        splay(x,0);splay(y,x);
        st[st[y].ch[0]].rev^=1;
    }//翻转的操作就是将l-1转到根上,r+1转到根的右儿子,然后l到r这个区间就是根右儿子的左儿子(比较绕,可以画个图想一想
    inline void output(int p){
        push_down(p);
        if(st[p].ch[0]) output(st[p].ch[0]);
        if(st[p].val>=1&&st[p].val<=n) printf("%d ",st[p].val);
        if(st[p].ch[1]) output(st[p].ch[1]);
    }//输出的时候下推一下标记,输出顺序就是二叉树的顺序
    int main(){
        n=read();m=read();int i,j,k;
        insert(INF);insert(-INF);
        for(i=1;i<=n;i++){
            insert(i);
        }
        while(m--){
            int x,y;x=read();y=read();
            rev(x+1,y+1);
        }
        output(root);
        return 0;
    }
  • 相关阅读:
    Vijos P1459 车展 (treap 任意区间中位数)
    「BZOJ1691」[Usaco2007 Dec] 挑剔的美食家 (Treap)
    hdu 1540 Tunnel Warfare(Treap)
    hdu 2844 Coins (多重背包+二进制优化)
    hdu 2159 FATE (二维完全背包)
    hdu 2955 Robberies (01背包)
    hdu 2546 饭卡 (01背包)
    hdu 2191 (多重背包二进制优化)
    2019西北工业大学程序设计创新实践基地春季选拔赛 I Chino with Rewrite (并查集+树链剖分+线段树)
    CF895E Eyes Closed (期望)
  • 原文地址:https://www.cnblogs.com/wenci/p/10122634.html
Copyright © 2020-2023  润新知