• BZOJ 2588: Spoj 10628. Count on a tree


    2588: Spoj 10628. Count on a tree

    Time Limit: 12 Sec  Memory Limit: 128 MB
    Submit: 5394  Solved: 1272
    [Submit][Status][Discuss]

    Description

    给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第K小的点权。其中lastans是上一个询问的答案,初始为0,即第一个询问的u是明文。
     

    Input

    第一行两个整数N,M。
    第二行有N个整数,其中第i个整数表示点i的权值。
    后面N-1行每行两个整数(x,y),表示点x到点y有一条边。
    最后M行每行两个整数(u,v,k),表示一组询问。
     

    Output

     
    M行,表示每个询问的答案。

    Sample 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

    Sample Output

    2
    8
    9
    105
    7

    HINT




    HINT:

    N,M<=100000

    暴力自重。。。

    Source

    [Submit][Status][Discuss]

    树上主席树

     1 #include <bits/stdc++.h>
     2 const int siz = 200005, tre = 7000005;
     3 int n, m, q, val[siz], map[siz], tot, hd[siz], to[siz], nt[siz], edge, root[siz], ls[tre], rs[tre], sm[tre], cnt, vis[siz], fa[siz][21], dep[siz], qa[siz], qb[siz], tail;
     4 void insert(int &t, int f, int l, int r, int p) {
     5     t = ++cnt; ls[t] = ls[f], rs[t] = rs[f], sm[t] = sm[f] + 1;
     6     if (l != r) { int mid = (l + r) >> 1; (p <= mid ? insert(ls[t], ls[f], l, mid, p) : insert(rs[t], rs[f], mid + 1, r, p)); }
     7 }
     8 void dfs(int u, int f) { vis[u] = 1; 
     9     dep[u] = dep[f] + 1, fa[u][0] = f;
    10     insert(root[u], root[f], 1, tot, val[u]);
    11     for (int i = 1; i <= 20; ++i)fa[u][i] = fa[fa[u][i - 1]][i - 1];
    12     for (int i = hd[u]; i; i = nt[i])if (to[i] != f)dfs(to[i], u);
    13 }
    14 inline int lca(int a, int b) {
    15     if (dep[a] < dep[b])a ^= b ^= a ^= b;
    16     for (int i = 20; ~i; --i)if (dep[fa[a][i]] >= dep[b])a = fa[a][i];
    17     for (int i = 20; ~i; --i)if (fa[a][i] ^ fa[b][i])a = fa[a][i], b = fa[b][i];
    18     return a == b ? a : fa[a][0];
    19 }
    20 inline void add(int a, int b) { qa[tail] = root[a], qb[tail++] = b; }
    21 int qry(int l, int r, int k) { if (l == r)return l; int s = 0, mid = (l + r) >> 1; 
    22     for (int i = 0; i < tail; ++i)s += qb[i] * sm[ls[qa[i]]];
    23     for (int i = 0; i < tail; ++i)qa[i] = s < k ? rs[qa[i]] : ls[qa[i]];
    24     return s < k ? qry(mid + 1, r, k - s) : qry(l, mid, k);
    25 }
    26 inline void adde(int x, int y) {
    27     nt[++edge] = hd[x], to[edge] = y, hd[x] = edge,
    28     nt[++edge] = hd[y], to[edge] = x, hd[y] = edge;
    29 }
    30 signed main(void) {
    31     scanf("%d%d", &n, &q); m = n - 1;
    32     for (int i = 1; i <= n; ++i)scanf("%d", val + i), map[++tot] = val[i];
    33     std::sort(map + 1, map + tot + 1); tot = std::unique(map + 1, map + tot + 1) - map;
    34     for (int i = 1; i <= n; ++i)val[i] = std::lower_bound(map + 1, map + tot, val[i]) - map;
    35     for (int i = 1, x, y; i <= m; ++i)scanf("%d%d", &x, &y), adde(x, y);
    36     for (int i = 1; i <= n; ++i)if (!vis[i])dfs(i, 0);
    37     for (int i = 1, ans = 0, x, y, k, t; i <= q; ++i) { 
    38         scanf("%d%d%d", &x, &y, &k), x ^= ans, tail = 0, 
    39         add(x, 1), add(y, 1), add(t = lca(x, y), -1), add(fa[t][0], -1), printf("%d", ans = map[qry(1, tot, k)]); if (i != q)puts("");
    40     }
    41 }

    @Author: YouSiki

  • 相关阅读:
    loj#2540. 「PKUWC2018」随机算法
    loj#2538. 「PKUWC2018」Slay the Spire
    loj#2537. 「PKUWC2018」Minimax
    CF662C Binary Table
    bzoj4589: Hard Nim
    【HDU5909】Tree Cutting(FWT)
    P3175 [HAOI2015]按位或
    P4389 付公主的背包
    P4233 射命丸文的笔记
    GFS分布式文件系统环境部署与管理
  • 原文地址:https://www.cnblogs.com/yousiki/p/6275230.html
Copyright © 2020-2023  润新知