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\n", 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\n", mid, x);
            if(check(mid, u, v) > k) l = mid;
            else r = ans = mid;
        }
        printf("%d\n", 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

 

posted @ 2017-08-06 15:28  19992147  阅读(123)  评论(0编辑  收藏  举报