zoukankan      html  css  js  c++  java
  • P3391 文艺平衡树(Splay做法)

    您需要写一种数据结构(可参考题目标题),来维护一个有序数列。

    其中需要提供以下操作:翻转一个区间,例如原有序序列是 5 4 3 2 15 4 3 2 1,翻转区间是 [2,4][2,4] 的话,结果是 5 2 3 4 15 2 3 4 1。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+100;
    const int inf=1e9;
    int n,m;
    struct Splay_tree {
        int fa;
        int cnt;
        int ch[2];
        int v;
        int size;
        int lazy;
    }t[maxn];
    int root,tot;
    void update (int x) {
        t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+t[x].cnt;
    }
    void pushdown (int x) {
        if (t[x].lazy) {
            t[t[x].ch[0]].lazy^=1;
            t[t[x].ch[1]].lazy^=1;
            t[x].lazy=0;
            swap(t[x].ch[0],t[x].ch[1]);
        }
    }
    void rotate (int x) {
        int y=t[x].fa;
        int z=t[y].fa;
        int k=(t[y].ch[1]==x);
        t[z].ch[t[z].ch[1]==y]=x;
        t[x].fa=z;
        t[y].ch[k]=t[x].ch[k^1];
        t[t[x].ch[k^1]].fa=y;
        t[x].ch[k^1]=y;
        t[y].fa=x;
        update(y);
        update(x);
    }
    void splay (int x,int s) {
        while (t[x].fa!=s) {
            int y=t[x].fa;
            int z=t[y].fa;
            if (z!=s) 
                (t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
            rotate(x);
        }
        if (s==0) root=x;
    }
    void find (int x) {
        int u=root;
        if (!u) return;
        while (t[u].ch[x>t[u].v]&&x!=t[u].v) 
            u=t[u].ch[x>t[u].v];
        splay(u,0);
    }
    void ins (int x) {
        int u=root;
        int fa=0;
        while (u&&t[u].v!=x) {
            fa=u;
            u=t[u].ch[x>t[u].v];
        }
        if (u)
            t[u].cnt++;
        else {
            u=++tot;
            if (fa)
                t[fa].ch[x>t[fa].v]=u;
            t[u].ch[0]=t[u].ch[1]=0;
            t[tot].fa=fa;
            t[tot].v=x;
            t[tot].cnt=1;
            t[tot].size=1;
        }
        splay(u,0); 
    }
    int Next (int x,int f) {
        find(x);
        int u=root;
        if (t[u].v>x&&f) return u;
        if (t[u].v<x&&!f) return u;
        u=t[u].ch[f];
        while (t[u].ch[f^1]) u=t[u].ch[f^1];
        return u;
    } 
    void del (int x) {
        int lst=Next(x,0);
        int nxt=Next(x,1);
        splay(lst,0);
        splay(nxt,lst);
        int tt=t[nxt].ch[0];
        if (t[tt].cnt>1) {
            t[tt].cnt--;
            splay(tt,0);
        }
        else 
            t[nxt].ch[0]=0;
    }
    int kth (int x) {
        int u=root;
        while (t[u].size<x) return 0;
        while (1) {
            pushdown(u);
            int y=t[u].ch[0];
            if (x>t[y].size+t[u].cnt) {
                x-=t[y].size+t[u].cnt;
                u=t[u].ch[1];
            }
            else if (t[y].size>=x) 
                u=y;
            else
                return t[u].v;
        }
    }
    void reverse (int l,int r) {
        l=kth(l);
        r=kth(r+2);
        splay(l,0);
        splay(r,l);
        t[t[t[root].ch[1]].ch[0]].lazy^=1; 
    }
    void dfs (int u) {
        pushdown(u);
        if (t[u].ch[0])
            dfs(t[u].ch[0]);
        if (t[u].v>1&&t[u].v<n+2)printf("%d ",t[u].v-1);
        if (t[u].ch[1])
            dfs(t[u].ch[1]);
    }
    int main () {
        scanf("%d%d",&n,&m);
    
        for (int i=1;i<=n+2;i++) ins(i);
        for (int i=1;i<=m;i++) {
            int l,r;
            scanf("%d%d",&l,&r);
            reverse(l,r);
        }
        dfs(root);
    }
  • 相关阅读:
    CentOS(九)--与Linux文件和目录管理相关的一些重要命令①
    CentOS(八)--crontab命令的使用方法
    CentOS(七)--Linux文件类型及目录配置
    CentOS(六)--Linux系统的网络环境配置
    ActionBar实现顶部返回键,顶部按钮
    安卓---高德地图API应用
    安卓---achartengine图表----简单调用----使用view显示在自己的布局文件中----actionBar的简单设置
    安卓访问webAPI,并取回数据
    webAPI---发布(IIS)--发布遇到问题(500.19,500.21,404.8,404.3)
    安卓----短信验证(借用第三方平台)
  • 原文地址:https://www.cnblogs.com/zhanglichen/p/13417409.html
Copyright © 2011-2022 走看看