zoukankan      html  css  js  c++  java
  • [SPOJ10628]Count on a tree(主席树)

    题目链接

    题目描述

    给你一棵有n个结点的树,节点编号为1~n。

    每个节点都有一个权值。

    要求执行以下操作:

    U V K:求从节点u到节点v的第k小权值。

    Solution

    树上主席树裸题。

    思路和序列差不多,树上前缀和即可。

    可持久化时的前一个版本就是它的父亲。

    设查询(u,v),值就是u+v-lca-fa[lca]

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    const int N = 100010;
    struct chairman_tree{
        int val;
        int ls, rs;
    }tr[N * 20];
    int rt[N], tot;
    struct node{
        int pre, to;
    }edge[N << 1];
    int head[N], tt;
    int n, m, a[N], b[N], nn;
    int sz[N], bl[N], dep[N], f[N], son[N], tn[N];
    int lastans;
    void ins(int &cur, int pre, int l, int r, int pos) {
        cur = ++tot;
        tr[cur] = tr[pre];
        tr[cur].val++;
        if (l == r) return;
        int mid = (l + r) >> 1;
        if (pos <= mid) ins(tr[cur].ls, tr[pre].ls, l, mid, pos);
        else ins(tr[cur].rs, tr[pre].rs, mid + 1, r, pos); 
    }
    int ask(int o, int p, int q, int s, int l, int r, int k) {
        if (l == r) return l;
        int mid = (l + r) >> 1;
        int num = tr[tr[o].ls].val + tr[tr[p].ls].val - tr[tr[q].ls].val - tr[tr[s].ls].val;
        if (k <= num) return ask(tr[o].ls, tr[p].ls, tr[q].ls, tr[s].ls, l, mid, k);
        else return ask(tr[o].rs, tr[p].rs, tr[q].rs, tr[s].rs, mid + 1, r, k - num);
    }
    void dfs(int x, int fa) {
        sz[x] = 1;
        son[x] = 0;
        ins(rt[x], rt[fa], 1, nn, a[x]);
        for (int i = head[x]; i; i = edge[i].pre) {
            int y = edge[i].to;
            if (y == fa) continue;
            dep[y] = dep[x] + 1;
            f[y] = x;
            dfs(y, x);
            sz[x] += sz[y];
            if (sz[y] > sz[son[x]]) {
                son[x] = y;
            }
        }
    }
    void dfs2(int x, int chain) {
        bl[x] = chain;
        if (son[x]) dfs2(son[x], chain);
        for (int i = head[x]; i; i = edge[i].pre) {
            int y = edge[i].to;
            if (y != f[x] && y != son[x]) {
                dfs2(y, y);
            }
        }
    }
    int LCA(int u, int v) {
        while (bl[u] != bl[v]) {
            if (dep[bl[u]] < dep[bl[v]]) swap(u, v);
            u = f[bl[u]];
        }
        return dep[u] < dep[v] ? u : v;
    }
    void add(int u, int v) {
        edge[++tt] = node{head[u], v};
        head[u] = tt; 
    }
    int main() {
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            b[++nn] = a[i];
        }
        sort(b + 1, b + nn + 1);
        nn = unique(b + 1, b + nn + 1) - b - 1;
        for (int i = 1; i <= n; i++) {
            int p = lower_bound(b + 1, b + nn + 1, a[i]) - b;
            tn[p] = a[i];
            a[i] = p;
        }
        for (int i = 1, u, v; i < n; i++) {
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        dfs(1, 0);
        dfs2(1, 1);
        while (m--) {
            int u, v, k;
            scanf("%d%d%d", &u, &v, &k);
            u ^= lastans;
            int lca = LCA(u, v);
            lastans = tn[ask(rt[u], rt[v], rt[lca], rt[f[lca]], 1, nn, k)];
            printf("%d
    ", lastans);
        }
        return 0;
    }
  • 相关阅读:
    SSL证书安装指引
    腾讯云中ssL证书的配置安装
    微信小程序:微信登陆(ThinkPHP作后台)
    TPshop学习(8)微信支付
    LNMP安装Let’s Encrypt 免费SSL证书方法:自动安装与手动配置Nginx
    ruby文档
    tesseract-ocr图片识别开源工具
    Python读写文件
    百度贴吧的网络爬虫(v0.4)源码及解析
    中文分词库
  • 原文地址:https://www.cnblogs.com/zcr-blog/p/12736716.html
Copyright © 2011-2022 走看看