zoukankan      html  css  js  c++  java
  • Count on a tree(SPOJ COT + 树上第k大 + 主席树 + LCA)

    题目链接:https://www.spoj.com/problems/COT/en/

    题目:

    题意:

      给你一棵有n个节点的树,求节点u到节点v这条链上的第k大。

    思路:

      我们首先用dfs进行建题目给的树,然后在dfs时进行主席树的update操作。众所周知,主席树采用的是前缀和思想,区间第k大是与前一个树添加新的线段树,而树上第k大则是与父亲节点添加新的线段树,因而在此思想上此题的答案为sum[u] + sum[v] - sum[lca(u,v)] - sum[fa[lca(u,v)]。求第k大操作和区间第k大一样,就不描述了~

    代码实现如下:

      1 #include <set>
      2 #include <map>
      3 #include <queue>
      4 #include <stack>
      5 #include <cmath>
      6 #include <ctime>
      7 #include <bitset>
      8 #include <cstdio>
      9 #include <string>
     10 #include <vector>
     11 #include <cstdlib>
     12 #include <cstring>
     13 #include <iostream>
     14 #include <algorithm>
     15 using namespace std;
     16 
     17 typedef long long LL;
     18 typedef pair<LL, LL> pLL;
     19 typedef pair<LL, int> pli;
     20 typedef pair<int, LL> pil;;
     21 typedef pair<int, int> pii;
     22 typedef unsigned long long uLL;
     23 
     24 #define lson rt<<1
     25 #define rson rt<<1|1
     26 #define lowbit(x) x&(-x)
     27 #define name2str(name) (#name)
     28 #define bug printf("*********
    ");
     29 #define debug(x) cout<<#x"=["<<x<<"]" <<endl;
     30 #define FIN freopen("/home/dillonh/CLionProjects//in.txt", "r", stdin);
     31 #define FOUT freopen("D://code//out.txt", "w", stdout);
     32 #define IO ios::sync_with_stdio(false),cin.tie(0);
     33 
     34 const double eps = 1e-9;
     35 const int mod = 1000000007;
     36 const int maxn = 100000 + 7;
     37 const double pi = acos(-1);
     38 const int inf = 0x3f3f3f3f;
     39 const LL INF = 0x3f3f3f3f3f3f3f3fLL;
     40 
     41 int n, q, tot, cnt, x, y, k, len;
     42 int head[maxn], root[maxn];
     43 int a[maxn], deep[maxn], fa[maxn][30];
     44 vector<int> v;
     45 
     46 struct edge {
     47     int v, next;
     48 }ed[maxn<<1];
     49 
     50 void addedge(int u, int v) {
     51     ed[tot].v = v;
     52     ed[tot].next = head[u];
     53     head[u] = tot++;
     54     ed[tot].v = u;
     55     ed[tot].next = head[v];
     56     head[v] = tot++;
     57 }
     58 
     59 struct node {
     60     int l, r, sum;
     61 }tree[maxn*40];
     62 
     63 int getid(int x) {
     64     return lower_bound(v.begin(), v.end(), x) - v.begin() + 1;
     65 }
     66 
     67 void update(int l, int r, int& x, int y, int pos) {
     68     tree[++cnt] = tree[y], tree[cnt].sum++, x = cnt;
     69     if(l == r) return;
     70     int mid = (l + r) >> 1;
     71     if(mid >= pos) update(l, mid, tree[x].l, tree[y].l, pos);
     72     else update(mid + 1, r, tree[x].r, tree[y].r, pos);
     73 }
     74 
     75 int query(int l, int r, int x, int y, int p, int pp, int k) {
     76     if(l == r) return l;
     77     int mid = (l + r) >> 1;
     78     int sum = tree[tree[x].l].sum + tree[tree[y].l].sum - tree[tree[p].l].sum - tree[tree[pp].l].sum;
     79     if(sum >= k) return query(l, mid, tree[x].l, tree[y].l, tree[p].l, tree[pp].l, k);
     80     else return query(mid + 1, r, tree[x].r, tree[y].r, tree[p].r, tree[pp].r, k - sum);
     81 }
     82 
     83 void dfs(int u, int d, int p) {
     84     deep[u] = d;
     85     fa[u][0] = p;
     86     update(1, len, root[u], root[p], getid(a[u]));
     87     for(int i = head[u]; ~i; i = ed[i].next) {
     88         int v = ed[i].v;
     89         if(v != p) {
     90             dfs(v, d + 1, u);
     91         }
     92     }
     93 }
     94 
     95 void lca() {
     96     for(int i = 1; i <= n; i++) {
     97         for(int j = 1; (1 << j) <= n; j++) {
     98             fa[i][j] = -1;
     99         }
    100     }
    101     for(int j = 1; (1 << j) <= n; j++) {
    102         for(int i = 1; i <= n; i++) {
    103             if(fa[i][j-1] != -1) {
    104                 fa[i][j] = fa[fa[i][j-1]][j-1];
    105             }
    106         }
    107     }
    108 }
    109 
    110 int cal(int u, int v) {
    111     if(deep[u] < deep[v]) swap(u, v);
    112     int k;
    113     for(k = 0; (1 << (1 + k)) <= deep[u]; k++);
    114     for(int i = k; i >= 0; i--) {
    115         if(deep[u] - (1 << i) >= deep[v]) {
    116             u = fa[u][i];
    117         }
    118     }
    119     if(u == v) return u;
    120     for(int i = k; i >= 0; i--) {
    121         if(fa[u][i] != -1 && fa[u][i] != fa[v][i]) {
    122             u = fa[u][i];
    123             v = fa[v][i];
    124         }
    125     }
    126     return fa[u][0];
    127 }
    128 
    129 int main() {
    130 #ifndef ONLINE_JUDGE
    131     FIN;
    132 #endif
    133     scanf("%d%d", &n, &q);
    134     memset(head, -1, sizeof(head));
    135     for(int i = 1; i <= n; i++) scanf("%d", &a[i]), v.push_back(a[i]);
    136     sort(v.begin(), v.end());
    137     v.erase(unique(v.begin(), v.end()), v.end());
    138     len = v.size();
    139     for(int i = 1; i < n; i++) scanf("%d%d", &x, &y), addedge(x, y);
    140     dfs(1, 1, 0);
    141     lca();
    142     while(q--) {
    143         scanf("%d%d%d", &x, &y, &k);
    144         int p = cal(x, y);
    145         printf("%d
    ", v[query(1, len, root[x], root[y], root[p], root[fa[p][0]], k)-1]);
    146     }
    147     return 0;
    148 }
  • 相关阅读:
    20120410日常记录
    20120229
    20120307
    20120411记录
    javaScript OOP学习总结
    vue.js初学习
    SQL Server 2008 r2 新建实例无法远程访问 Error:40
    SSRS 中表格报表分组字段含有NULL
    Iframe中的SSRS报表中使用windows.open在新窗口中不能打开URL中的问题
    SSIS中的Unicode,非Unicode问题
  • 原文地址:https://www.cnblogs.com/Dillonh/p/9719523.html
Copyright © 2011-2022 走看看