• spoj 10628


    http://www.spoj.com/problems/COT/ 树上第k小元素

    LCA + 可持久化线段树

    每个新的版本都是由其父亲版本转化而来。

      1 #include <cstdio>
      2 #include <iostream>
      3 #include <algorithm>
      4 #include <cstring>
      5 
      6 using namespace std;
      7 
      8 const int maxn = 1e5 + 5;
      9 const int maxd = 20;
     10 struct Edge{
     11     int v, next;
     12 }p[maxn << 1];
     13 int head[maxn], e, d[maxn], f[maxn][maxd];
     14 //LCA
     15 void init(){
     16     memset(d, 0, sizeof(d));
     17     memset(f, 0, sizeof(f));
     18     memset(head, -1, sizeof(head));
     19     e = 0;
     20 }
     21 void addEdge(int u, int v){
     22     p[e].v = v; p[e].next = head[u]; head[u] = e++;
     23     swap(u, v);
     24     p[e].v = v; p[e].next = head[u]; head[u] = e++;
     25 }
     26 int lca(int u, int v){
     27     if (d[u] < d[v]) swap(u, v);
     28     int k = d[u] - d[v];
     29     for (int i = 0; i < maxd;  ++i)
     30         if ((1 << i) & k) u = f[u][i];
     31     if (u == v) return u;
     32     for (int i = maxd - 1; i >= 0; --i){
     33         if (f[u][i] != f[v][i]){
     34             u = f[u][i];
     35             v = f[v][i];
     36         }
     37     }
     38     return f[u][0];
     39 }
     40 //CMT
     41 int ls[maxn * 40], rs[maxn * 40], sum[maxn * 40], T[maxn], tot, rt;
     42 int num[maxn], san[maxn], n, m; // 离散化前点数,离散化后点数 
     43 void init_hash(){
     44     for (int i = 1; i <= n; ++i) san[i] = num[i];
     45     sort(san + 1, san + n + 1);
     46     m = unique(san + 1, san + n + 1) - san - 1;
     47 }
     48 int hash(int x){
     49     return lower_bound(san + 1, san + m + 1, x) - san;
     50 }
     51 void build(int l, int r, int& rt){
     52     rt = ++ tot; sum[rt] = 0;
     53     if (l == r) return;
     54     int mid = (l + r) >> 1;
     55     build(l, mid, ls[rt]);
     56     build(mid + 1, r, rs[rt]);
     57 }
     58 void update(int last, int pos, int l, int r, int& rt){
     59     rt = ++ tot;
     60     ls[rt] = ls[last], rs[rt] = rs[last], sum[rt] = sum[last] + 1;
     61     if (l == r) return ;
     62     int mid = (l + r) >> 1;
     63     if (pos <= mid) update(ls[last], pos, l, mid, ls[rt]);
     64     else update(rs[last], pos, mid + 1, r, rs[rt]);
     65 }
     66 int query(int pos, int left_rt, int right_rt, int lca_rt, int l, int r, int k){
     67     if (l == r) return l;
     68     int mid = (l + r) >> 1;
     69     int cnt = sum[ls[left_rt]] + sum[ls[right_rt]] - 2 * sum[ls[lca_rt]] + (pos >= l && pos <= mid);//注意lca为跟的时候
     70     if (k <= cnt) return query(pos, ls[left_rt], ls[right_rt], ls[lca_rt], l, mid, k);
     71     else return query(pos, rs[left_rt], rs[right_rt], rs[lca_rt], mid + 1, r, k - cnt);
     72 }
     73 //LCA && CMT
     74 void dfs(int u, int fa){
     75     f[u][0] = fa;//注意
     76     d[u] = d[f[u][0]] + 1;
     77     update(T[fa], hash(num[u]), 1, m, T[u]);
     78     for (int i = 1; i < maxd; ++i) f[u][i] = f[ f[u][i - 1] ][i - 1];
     79     for (int i = head[u]; ~i; i = p[i].next){
     80         if (p[i].v == fa) continue;
     81         dfs(p[i].v, u);
     82     }
     83 }
     84 int main(){
     85     int q, u, v, k;
     86     while (scanf("%d%d", &n, &q) == 2){
     87         for (int i = 1; i <= n; ++i) scanf("%d", &num[i]);
     88         init();
     89         init_hash();
     90         tot = 0;
     91         for (int i = 1; i < n; ++i){
     92             scanf("%d%d", &u, &v);
     93             addEdge(u, v);
     94         }
     95         build(1, m, T[0]);
     96         dfs(1, 0);
     97         while (q--){
     98             scanf("%d%d%d", &u, &v, &k);
     99             printf("%d
    ",san[query(hash(num[lca(u, v)]), T[u], T[v], T[lca(u, v)],1, m, k)]);
    100         }
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    Git
    Shell-sed之替换字符
    Linux IO/NFS tunning 性能优化及检测
    利用Java Flight Recorder(JFR)诊断timing及内存问题
    Get/Post
    SQL-1
    HTTP协议简要
    nmap简单使用
    (C语言)买东西找零钱
    今日错误(C语言)(定义二维数组储存)
  • 原文地址:https://www.cnblogs.com/Missa/p/3336449.html
Copyright © 2020-2023  润新知