• P2633 Count on a tree


    给定一棵 n 个节点的树,每个点有一个权值。有 m 个询问,每次给你 u,v,k,你需要回答u xor last 和 v 这两个节点间第 k 小的点权。

    其中 last 是上一个询问的答案,定义其初始为 0,即第一个询问的 u 是明文。

    输入格式
    第一行两个整数 n,m

    第二行有 n 个整数,其中第 i个整数表示点 i 的权值。

    后面 n-1行每行两个整数 x,y表示点 x 到点 y有一条边。

    最后 m行每行两个整数 u,v,k表示一组询问。

    输出格式
    m行,每行一个正整数表示每个询问的答案。

    input
    8 5 105 2 9 3 8 5 7 7 1 2 1 3 1 4 3 5 3 6 3 7 4 8 2 5 1 0 5 2 10 5 3 11 5 4 110 8 2

    output
    2
    8
    9
    105
    7

    1≤n,m≤1E5

    Sol:建立主席树,第i个主席树为,从根到i这一条链上的信息。
    于是询问x,y这一条链上的第K大问题,就变成了第x棵树的信息+第Y棵树的-第Lca(x,y)-第father(lca(x,y))

    #include <iostream>
    #include <cstring>
    #include <string>
    #include <algorithm>
    #include <vector>
    #include <cmath>
    #include <cstdio>
    #include <cstdlib>
    #define ll long long
    using namespace std;
    const int N = 2e5+5;
    int root[N], cnt;
    int lisan[N];
    int su[N];
    int mx;
    int tot = 1;
    int he[N], ne[N<<1], ver[N<<1];
    int f[N][20];
    int dep[N];
    void add(int x, int y)
    {
        ne[++tot] = he[x];
        ver[tot] = y;
        he[x] = tot;
    }
    struct Node
    {
        int l, r, sum;
    }tr[N<<5];
    inline int getn(int g)
    {
        return lower_bound(lisan+1, lisan+mx, g) - lisan;
    }
    void change(int l, int r, int &p, int pre, int v)
    {
        tr[++cnt] = tr[pre];
        p = cnt;
        tr[p].sum++;
        if (l == r) 
    	    return;
        int mid = (l+r) >>1;
        if (v <= mid) 
    	    change(l, mid, tr[p].l, tr[pre].l, v);
        else 
    	    change(mid+1, r,tr[p].r, tr[pre].r, v);
    }
    void dfs(int u, int fa)
    {
        change(1, mx-1, root[u], root[fa], getn(su[u]));
        f[u][0] = fa;
        dep[u] = dep[fa] + 1;
        for (int i = 1; i <= 18; i++)
            f[u][i] = f[f[u][i-1]][i-1];
        for (int i = he[u]; i; i = ne[i])
        {
            int y = ver[i];
            if (y == fa) continue;
            dfs(y, u);
        }
    }
    int lca(int x, int y)
    {
        if (dep[x] > dep[y]) 
    	    swap(x, y);
        for (int i = 18; i >= 0; i--)
        {
            if (dep[f[y][i]] < dep[x]) continue;
            y = f[y][i];
        }
        if (x == y) 
    	    return x;
        for (int i = 18; i >= 0; i--)
            if (f[x][i] != f[y][i]) 
    		    x = f[x][i], y = f[y][i];
        return f[x][0];
    }
    int ask(int l, int r, int x, int y, int z, int w, int k)
    {
        if (l == r) 
    	    return l;
        int sum = tr[tr[x].l].sum + tr[tr[y].l].sum - tr[tr[z].l].sum - tr[tr[w].l].sum;
        int mid = (l + r) >> 1;
        if (sum >= k) 
    	    return ask(l, mid, tr[x].l, tr[y].l, tr[z].l, tr[w].l, k);
        return 
    	     ask(mid+1, r, tr[x].r, tr[y].r, tr[z].r, tr[w].r, k-sum);
    }
    int mask(int x, int y, int k)
    {
        int _lca = lca(x, y);
        return lisan[ask(1, mx-1, root[x], root[y], root[_lca], root[f[_lca][0]], k)];
    }
    int main()
    {
        int n, m;
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++)
        {
            scanf("%d", &su[i]);
            lisan[++mx] = su[i];
        }
        sort(lisan+1, lisan+mx+1);
        mx = unique(lisan+1, lisan+mx+1) - lisan;
        for (int i= 1; i < n; i++)
        {
            int x, y;
            scanf("%d%d", &x, &y);
            add(x, y); 
    		add(y, x);
        }
        dfs(1, 0);
        int la = 0;
        while(m--)
        {
            int x, y, k;
            scanf("%d%d%d", &x, &y, &k);
            printf("%d
    ", la = mask(x^la, y, k));
        }
        return 0;
    }
    
    //https://blog.csdn.net/qq_35802619/article/details/101717621
    

      

    如果变成带修改的话

    [BZOJ1146][CTSC2008]网络管理Network(树状数组套线段树)

    https://blog.csdn.net/xyz32768/article/details/81458418?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-2.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-2.control

  • 相关阅读:
    Leo程序员羊皮卷文摘(更新ing)
    ubuntu下的yuv播放器
    浏览器之一
    海量数据处理常用思路和方法(zh)
    我本将心向明月,奈何明月照沟渠
    转载光纤通信之父
    重装系统或是更换电脑之后,Foxmail的恢复
    关于录制Linux视频
    Linux之路(原发表于07年,现在搬到博客)
    Gentoo安装 miniCD+stage3
  • 原文地址:https://www.cnblogs.com/cutemush/p/14641581.html
Copyright © 2020-2023  润新知