zoukankan      html  css  js  c++  java
  • 「luogu3380」【模板】二逼平衡树(树套树)

    「luogu3380」【模板】二逼平衡树(树套树)

    传送门
    我写的树套树——线段树套平衡树。
    线段树上的每一个节点都是一棵 ( ext{FHQ Treap}) ,然后我们就可以根据平衡树的基本操作以及线段树上区间信息可合并的性质来实现了,具体细节看代码都懂。
    参考代码:

    #include <algorithm>
    #include <cstdlib>
    #include <cstdio>
    #define rg register
    #define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
    using namespace std;
    template < class T > inline void read(T& s) {
        s = 0; int f = 0; char c = getchar();
        while ('0' > c || c > '9') f |= c == '-', c = getchar();
        while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
        s = f ? -s : s;
    }
    
    const int _ = 50010, __ = 2000010, INF = 2147483647;
    
    int n, m, A[_];
    int tot, ch[2][__], siz[__], pri[__], val[__];
    
    struct node {
        int rt, a, b, c;
        
        inline int Newnode(int v) { return siz[++tot] = 1, val[tot] = v, pri[tot] = rand(), tot; }
        
        inline void pushup(int p) { siz[p] = siz[ch[0][p]] + siz[ch[1][p]] + 1; }
        
        inline void split(int p, int v, int& x, int& y) {
    	    if (!p) { x = y = 0; return ; }
    	    if (val[p] <= v) return x = p, split(ch[1][p], v, ch[1][x], y), pushup(p);
    	    else return y = p, split(ch[0][p], v, x, ch[0][y]), pushup(p);
        }
        
        inline int merge(int x, int y) {
    	    if (!x || !y) return x + y;
    	    if (pri[x] > pri[y]) return ch[1][x] = merge(ch[1][x], y), pushup(x), x;
    	    else return ch[0][y] = merge(x, ch[0][y]), pushup(y), y;
        }
        
        inline void insert(int v) { split(rt, v, a, b), rt = merge(a, merge(Newnode(v), b)); }
        
        inline void erase(int v) { split(rt, v, a, c), split(a, v - 1, a, b), b = merge(ch[0][b], ch[1][b]), rt = merge(a, merge(b, c)); }
        
        inline void build(int l, int r) { for (rg int i = l; i <= r; ++i) insert(A[i]); }
        
        inline int kth(int p, int k) {
    	    if (siz[ch[0][p]] + 1 > k) return kth(ch[0][p], k);
        	if (siz[ch[0][p]] + 1 == k) return val[p];
    	    if (siz[ch[0][p]] + 1 < k) return kth(ch[1][p], k - siz[ch[0][p]] - 1);
        }
        
        inline int pre(int v) { split(rt, v - 1, a, b), c = a != 0 ? kth(a, siz[a]) : -INF, rt = merge(a, b); return c; }
        
        inline int nxt(int v) { split(rt, v, a, b), c = b != 0 ? kth(b, 1) : INF, rt = merge(a, b); return c; }
        
        inline int rank(int v) { split(rt, v - 1, a, b), c = siz[a] + 1, rt = merge(a, b); return c; }
    } t[_ << 2];
    
    inline int lc(int p) { return p << 1; }
    
    inline int rc(int p) { return p << 1 | 1; }
    
    inline void build(int p = 1, int l = 1, int r = n) {
        t[p].build(l, r);
        if (l == r) return ;
        int mid = (l + r) >> 1;
        build(lc(p), l, mid), build(rc(p), mid + 1, r);
    }
    
    inline void update(int x, int v, int p = 1, int l = 1, int r = n) {
        t[p].erase(A[x]), t[p].insert(v);
        if (l == r) return ;
        int mid = (l + r) >> 1;
        if (x <= mid) update(x, v, lc(p), l, mid);
        else update(x, v, rc(p), mid + 1, r);
    }
    
    inline int rank(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
        if (ql <= l && r <= qr) return t[p].rank(v) - 1;
        int mid = (l + r) >> 1, res = 0;
        if (ql <= mid) res += rank(ql, qr, v, lc(p), l, mid);
        if (qr > mid) res += rank(ql, qr, v, rc(p), mid + 1, r);
        return res;
    }
    
    inline int kth(int ql, int qr, int k) {
        int l = 0, r = 100000000, res;
        while (l <= r) {
    	int mid = (l + r) >> 1;
    	if (rank(ql, qr, mid) + 1 <= k) res = mid, l = mid + 1; else r = mid - 1;
        }
        return res;
    }
    
    inline int pre(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
        if (ql <= l && r <= qr) return t[p].pre(v);
        int mid = (l + r) >> 1, res = -INF;
        if (ql <= mid) res = max(res, pre(ql, qr, v, lc(p), l, mid));
        if (qr > mid) res = max(res, pre(ql, qr, v, rc(p), mid + 1, r));
        return res;
    }
    
    inline int nxt(int ql, int qr, int v, int p = 1, int l = 1, int r = n) {
        if (ql <= l && r <= qr) return t[p].nxt(v);
        int mid = (l + r) >> 1, res = INF;
        if (ql <= mid) res = min(res, nxt(ql, qr, v, lc(p), l, mid));
        if (qr > mid) res = min(res, nxt(ql, qr, v, rc(p), mid + 1, r));
        return res;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
        file("cpp");
    #endif
        read(n), read(m);
        for (rg int i = 1; i <= n; ++i) read(A[i]);
        build();
        for (rg int opt, l, r, k, x; m--; ) {
    	    read(opt);
    	    if (opt == 1) read(l), read(r), read(k), printf("%d
    ", rank(l, r, k) + 1);
        	if (opt == 2) read(l), read(r), read(k), printf("%d
    ", kth(l, r, k));
        	if (opt == 3) read(x), read(k), update(x, k), A[x] = k;
        	if (opt == 4) read(l), read(r), read(k), printf("%d
    ", pre(l, r, k));
        	if (opt == 5) read(l), read(r), read(k), printf("%d
    ", nxt(l, r, k));
        }
        return 0;
    }
    
  • 相关阅读:
    使用jmeter进行性能测试-Jmeter教程及技巧汇总 (转)
    Linux防火墙(Iptables)的开启与关闭
    解决Unable to load R3 module ...VBoxDD.dll (VBoxDD):GetLastError=1790
    Linux如何修改文件/文件夹内所有文件的权限
    php抽象类的简单应用
    php接口和多态的概念以及简单应用
    关于php中数据访问的几点补充
    php中重写和final关键字的使用
    php中static静态关键字的使用
    php对象引用和析构函数的关系
  • 原文地址:https://www.cnblogs.com/zsbzsb/p/12232249.html
Copyright © 2011-2022 走看看