• bzoj1146


    树链剖分+二分+线段树套treap

    写题5分钟,调试2小时。。。

    很好理解,就是维护树链剖分的线段树改成线段树套treap,然后每次树套树删除一个数,插入一个数,二分一个数查找排名就行了

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 100010, M = 19992147;
    inline int read()
    {
        int x = 0, f = 1; char c = getchar();
        while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
        while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
    int n, q;
    int t[N];
    vector<int> G[N];
    struct Treap {
        int seed, cnt;
        int child[N * 50][2], tot[N * 50], key[N * 50], p[N * 50], size[N * 50];
        int rand()
        {
            seed = abs(seed * M + 12345);
            return seed;
        }
        void update(int x)
        {
            size[x] = size[child[x][0]] + size[child[x][1]] + tot[x];
        }
        void rotate(int &x, int t)
        {
            int y = child[x][t];
            child[x][t] = child[y][t ^ 1];
            child[y][t ^ 1] = x;
            update(x);
            update(y);
            x = y;
        }
        void insert(int &x, int val)
        {
            if(x == 0)
            {
                p[x = ++cnt] = rand();
                key[x] = val;
                tot[x] = 1;
                update(x);
            }
            else
            {
                if(key[x] == val)
                {
                    ++tot[x];
                    update(x);
                    return;
                }
                int t = val > key[x];
                insert(child[x][t], val);
                if(p[child[x][t]] > p[x]) rotate(x, t);
                update(x);
            }        
        }
        void erase(int &x, int val)
        {
            if(key[x] == val)
            {
                if(child[x][0] == 0 && child[x][1] == 0)
                {
                    --tot[x];
                    if(tot[x] == 0) x = 0;
                    else update(x);
                    return;
                }
                int t = p[child[x][0]] < p[child[x][1]];
                rotate(x, t);
                erase(child[x][t ^ 1], val);
            }
            else erase(child[x][val > key[x]], val);
            update(x);
        }
        int query(int x, int val)
        {
            if(x == 0) return 0;
    //        printf("key[%d]=%d val=%d
    ", x, key[x], val);    
            if(val == key[x]) return size[child[x][1]];    
            if(val < key[x]) return size[child[x][1]] + tot[x] + query(child[x][0], val);    
            return query(child[x][1], val);
        }
    } treap;
    namespace seg 
    {
        int root[N << 2], mir[N];
        void build(int l, int r, int x)
        {
            for(int i = l; i <= r; ++i) treap.insert(root[x], t[mir[i]]);
            if(l == r) return;
            int mid = (l + r) >> 1;
            build(l, mid, x << 1);
            build(mid + 1, r, x << 1 | 1);
        }
        void update(int l, int r, int x, int pos, int pre, int now)
        {
            treap.erase(root[x], pre);
            treap.insert(root[x], now);
            if(l == r) return;
            int mid = (l + r) >> 1;
            if(pos <= mid) update(l, mid, x << 1, pos, pre, now);
            else update(mid + 1, r, x << 1 | 1, pos, pre, now);
        }
        int query(int l, int r, int x, int a, int b, int k)
        {
            if(l > b || r < a) return 0;
            if(l >= a && r <= b) return treap.query(root[x], k);            
            int mid = (l + r) >> 1;
            return (query(l, mid, x << 1, a, b, k) + query(mid + 1, r, x << 1 | 1, a, b, k));
        }
    } using namespace seg;
    namespace heavy_light_decomposition
    {
        int dfs_clock;
        int dfn[N], top[N], fa[N], dep[N], size[N], son[N];
        void dfs(int u, int last)
        {
            size[u] = 1;
            for(int i = 0; i < G[u].size(); ++i)
            {
                int v = G[u][i];
                if(v == last) continue;
                dep[v] = dep[u] + 1;
                fa[v] = u;
                dfs(v, u);
                size[u] += size[v];
                if(size[v] > size[son[u]]) son[u] = v;
            }
        }
        void dfs(int u, int last, int acs)
        {
            dfn[u] = ++dfs_clock;
            mir[dfs_clock] = u;
            top[u] = acs;
            if(son[u]) dfs(son[u], u, acs);
            for(int i = 0; i < G[u].size(); ++i)
            {
                int v = G[u][i];
                if(v == last || v == son[u]) continue;
                dfs(v, u, v);
            }
        }
        void change(int a, int b)
        {
            update(1, n, 1, dfn[a], t[a], b);
            t[a] = b;
        }
        int lca(int u, int v)
        {
            while(top[u] != top[v])
            {
                if(dep[top[u]] < dep[top[v]]) swap(u, v);
                u = fa[top[u]];
            }
            return dep[u] < dep[v] ? u : v;
        }
        int dis(int u, int v)
        {
            int x = lca(u, v);
            return dep[u] + dep[v] - 2 * dep[x] + 1;
        }
        int check(int mid, int u, int v)
        {
            int ret = 0;
            while(top[u] != top[v])
            {
                if(dep[top[u]] < dep[top[v]]) swap(u, v);
                ret += query(1, n, 1, dfn[top[u]], dfn[u], mid);            
                u = fa[top[u]];
            }
            if(dep[u] < dep[v]) swap(u, v);
            ret += query(1, n, 1, dfn[v], dfn[u], mid); 
            return ret + 1;
        }
        void ask(int k, int u, int v)
        {
            int l = 0, r = 100000010, ans = 0;
            if(dis(u, v) < k) 
            {
                puts("invalid request!");
                return;
            }
            while(r - l > 1)
            {
                int mid = (l + r) >> 1, x = check(mid, u, v);
    //            printf("mid=%d x=%d
    ", mid, x);
                if(check(mid, u, v) > k) l = mid;
                else r = ans = mid;
            }
            printf("%d
    ", ans);
        }
    } using namespace heavy_light_decomposition;
    int main()
    {
        n = read();
        q = read();
        for(int i = 1; i <= n; ++i) t[i] = read();
        for(int i = 1; i < n; ++i)
        {
            int u = read(), v = read();
            G[u].push_back(v);
            G[v].push_back(u);
        }
        dfs(1, 0);
        dfs(1, 0, 1);
        build(1, n, 1);
        while(q--)
        {
            int opt, x, y;
            scanf("%d%d%d", &opt, &x, &y);
            if(opt == 0) change(x, y);
            else ask(opt, x, y);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    twitter分享问题(三)——Required oauth_verifier parameter not provided
    旋转数组的最小数字
    关系型数据库基础之:简单的数据查询
    twitter分享问题(一)——MISSING_ARG_APIKEY
    extern "C"的理解
    从一个链接错误探究GCC的链接库顺序
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    不使用资源文件动态创建对话框的做法
    GAE 博客——B3log Solo 0.4.0 正式版发布了!
    CodeBlocks启动多个进程实例的做法
  • 原文地址:https://www.cnblogs.com/19992147orz/p/7294934.html
Copyright © 2020-2023  润新知