zoukankan      html  css  js  c++  java
  • 【模板】树套树(线段树套Splay)

    如题,这是一个模板。。。

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <cctype>
    
    #define max(x, y) (x > y ? x : y)
    #define min(x, y) (x < y ? x : y)
    
    inline void read(int & x)
    {
        x = 0;
        int k = 1;
        char c = getchar();
        while (!isdigit(c))
            if (c == '-') c = getchar(), k = -1;
            else c = getchar();
        while (isdigit(c))
            x = (x << 1) + (x << 3) + (c ^ 48),
            c = getchar();
        x *= k;  
    }
    
    const int inf = 2147483647;
    const int N = 4001000;
    int n, m, tot, l, r, x, y, z, opt, mxa = -2147483647;
    int cnt[N], faz[N], val[N], siz[N], a[N], son[N][2], root[N];
    
    //=======================================================================
    //Splay
    
    inline int Getson(int u) { return son[faz[u]][1] == u; }
    
    inline void Pushup(int u) { siz[u] = siz[son[u][0]] + siz[son[u][1]] + cnt[u]; }
    
    inline int Getmin(int u) { while (son[u][0]) u = son[u][0]; return u; }
    
    inline int Getmax(int u) { while (son[u][1]) u = son[u][1]; return u; }
    
    inline int Getx(int rtid, int x)
    {
        int u = root[rtid], las = 0;
        while (u && val[las = u] != x)
            if (x >= val[u]) u = son[u][1];
            else u = son[u][0];
        return u ? u : las; 
    }
    
    void Rotate(int u)
    {
        int y = faz[u], z = faz[y], ch = Getson(u);
        int b = son[u][ch ^ 1], d = Getson(y);
        son[u][ch ^ 1] = y, son[y][ch] = b;
        faz[y] = u, faz[b] = y, faz[u] = z;
        if (z) son[z][d] = u;
        Pushup(y), Pushup(u);
    }
    
    void Splay(int rtid, int u, int tar)
    {
        while (faz[u] != tar)
        {
            if (faz[faz[u]] != tar)
                if (Getson(u) == Getson(faz[u])) Rotate(faz[u]);
                else Rotate(u);
            Rotate(u);
        }
        if (!tar) root[rtid] = u;
    }
    
    inline void Insert(int rtid, int x)
    {
        int u = root[rtid], las = 0;
        if (!root[rtid])
        {
            root[rtid] = u = ++tot;
            val[u] = x; siz[u] = cnt[u] = 1;
            faz[u] = son[u][0] = son[u][1] = 0;
            return;
        }
        while (true)
        {
            ++siz[u];
            if (x == val[u]) 
            {
                ++cnt[u];
                break;
            }
            las = u;
            if (x > val[u]) u = son[u][1];
            else u = son[u][0];
            if (!u)
            {
                u = ++tot, val[u] = x, faz[u] = las,
                son[las][x > val[las]] = u;
                son[u][0] = son[u][1] = 0, 
                siz[u] = cnt[u] = 1;
                break;    
            }
        }
        Splay(rtid, u, 0);
    }
    
    inline void Delete(int rtid, int x)
    {
        int u = root[rtid];
        while (u)
        if (x == val[u]) 
        {
            Splay(rtid, u, 0);
            if (cnt[u] > 1) { --cnt[u], --siz[u]; return; }
            if (!son[u][0] || !son[u][1]) 
            {
                root[rtid] = son[u][0] | son[u][1];
                faz[root[rtid]] = 0;
                return;
            }
            int newrt = Getmin(son[u][1]);
            faz[son[u][1]] = 0,
            faz[son[u][0]] = newrt,
            son[newrt][0] = son[u][0];
            Splay(rtid, newrt, 0);
            return;
        }
        else if (x > val[u]) u = son[u][1];
        else u = son[u][0];
    }
    
    inline int Getkth(int rtid, int k)
    {
        int u = root[rtid];
        if (siz[u] < k) return -inf;
        while (u)
            if (siz[son[u][0]] >= k) u = son[u][0];
            else if (siz[son[u][0]] + cnt[u] < k) k -= siz[son[u][0]] + cnt[u], u = son[u][1];
            else return val[u];
    }
    
    inline int Getrank(int rtid, int x)
    {
    //-------------------·½·¨Ò»------------------------
    //Wrong Answer
    /*    int u = Getx(rtid, x);
        Splay(rtid, u, 0);
        return siz[son[u][0]];
    */
    
    //-------------------·½·¨¶þ------------------------ 
    int sum = 0, u = root[rtid];
        while (u)
            if (x == val[u]) return sum + siz[son[u][0]];
            else if (x > val[u]) sum += siz[son[u][0]] + cnt[u], u = son[u][1];
            else u = son[u][0];
        return sum;
    }
    
    int Pre(int rtid, int x)
    {
        int u = Getx(rtid, x);
           if (val[u] < x) return val[u];
        Splay(rtid, u, 0);
        return son[u][0] == 0 ? -inf : val[Getmax(son[u][0])];
    }
    
    int Suf(int rtid, int x)
    {
        int u = Getx(rtid, x);
           if (val[u] > x) return val[u];
        Splay(rtid, u, 0);
        return son[u][1] == 0 ? inf : val[Getmin(son[u][1])];
    }
    
    //Splay End
    //=======================================================================
    //Segment tree Begin
    
    #define Root 1, 1, n
    #define Lson u << 1, l, mid
    #define Rson u << 1 | 1, mid + 1, r
    #define ls (u << 1)
    #define rs (u << 1 | 1)
    #define mid (l + r >> 1)
    #define MID (L + R >> 1)
    
    inline void Segins(int u, int l, int r, int p, int x)
    {
        Insert(u, x);
        if (l == r) return;
        if (p <= mid) Segins(Lson, p, x);
        else Segins(Rson, p, x);
    }
    
    inline void Segmdf(int u, int l, int r, int p, int x)
    {
        Delete(u, a[p]), Insert(u, x);
        if (l == r) { a[p] = x; return; }
        if (p <= mid) Segmdf(Lson, p, x);
        else Segmdf(Rson, p, x);
    }
    
    inline int Segrak(int u, int l, int r, int x, int y, int z)
    {
        if (l == x && r == y) return Getrank(u, z);
        if (y <= mid) return Segrak(Lson, x, y, z);
        if (x > mid) return Segrak(Rson, x, y, z);
        return Segrak(Lson, x, mid, z) + Segrak(Rson, mid + 1, y, z);
    }
    
    inline int Segpre(int u, int l, int r, int x, int y, int z)
    {
        if (l == x && r == y) return Pre(u, z);
        if (y <= mid) return Segpre(Lson, x, y, z);
        if (x > mid) return Segpre(Rson, x, y, z);
        return max(Segpre(Lson, x, mid, z), Segpre(Rson, mid + 1, y, z));
    }
    
    inline int Segsuf(int u, int l, int r, int x, int y, int z)
    {
        if (l == x && r == y) return Suf(u, z);
        if (y <= mid) return Segsuf(Lson, x, y, z);
        if (x > mid) return Segsuf(Rson, x, y, z);
        return min(Segsuf(Lson, x, mid, z), Segsuf(Rson, mid + 1, y, z));
    }
    
    inline int Segkth(int l, int r, int k)
    {
        int cur, L = 0, R = mxa + 1;
        while (L < R)
        {
            cur = Segrak(Root, l, r, MID);
            if (cur < k) L = MID + 1;
            else R = MID;
        }
        return L - 1;
    }
    
    signed main()
    {
        read(n), read(m);
        for (int i = 1; i <= n; ++i)
        {
            read(a[i]);
            Segins(Root, i, a[i]);
            mxa = max(mxa, a[i]);
        }
        for (int i = 1; i <= m; ++i)
        {
            read(opt);
            if (opt == 3) read(x), read(y), Segmdf(Root, x, y);
            else
            {
                read(l), read(r), read(x);
                if (opt == 1) printf("%d
    ", Segrak(Root, l, r, x) + 1);
                if (opt == 2) printf("%d
    ", Segkth(l, r, x));
                if (opt == 4) printf("%d
    ", Segpre(Root, l, r, x));
                if (opt == 5) printf("%d
    ", Segsuf(Root, l, r, x));
            }
        }
        return 0;
    }
  • 相关阅读:
    获取发布的头条的url,避免点击打开新的页面
    下载图片 保存至本地 返回路径
    线程运行的3个状态
    程序并发执行所需付出的时空开销
    web metrics dashboard 数据分析工具 看板 从可视化发现问题 避免sql重复写 调高效率
    Binary safe
    simple dynamic string
    a
    a
    从业务角度 减少代码执行的时间 和 因长时间执行的而带来的代码复杂性 日志恢复数据
  • 原文地址:https://www.cnblogs.com/yanyiming10243247/p/10057812.html
Copyright © 2011-2022 走看看