• hdu3078(lca / RMQ在线)


    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078

    题意: 给出一棵 n 个点的带点权值的树, 接下来有 q 组形如 k, x, y 的输入, 若 k == 0 则将 x 点的权值替换成 y, 否则输出 x 到 y 之间顶点地 k 大的权值.

    思路: 用一个数组 val 记录一下每个顶点的权值, 对于k == 0, 直接令 val[x] = y 即可 .

    对于询问, 可以先求出 lca, 再记录一下路径上的顶点的权值, sort 一下, 输出第 k 大的即可.

    代码:

     1 #include <iostream>
     2 #include <stdio.h>
     3 #include <math.h>
     4 #include <string.h>
     5 #include <algorithm>
     6 #include <vector>
     7 using namespace std;
     8 
     9 const int MAXN = 8e4 + 10;
    10 vector<int> vt[MAXN];
    11 int dp[MAXN << 1][30];
    12 int first[MAXN], ver[MAXN << 1], deep[MAXN << 1];
    13 int pre[MAXN], val[MAXN], yy[MAXN], ip = 0, indx = 0;
    14 
    15 bool cmp(int x, int y){
    16     return x > y;
    17 }
    18 
    19 void dfs(int u, int h, int fa){
    20     pre[u] = fa;
    21     ver[++indx] = u;
    22     deep[indx] = h;
    23     first[u] = indx;
    24     for(int i = 0; i < vt[u].size(); i++){
    25         int v = vt[u][i];
    26         if(v != fa){
    27             dfs(v, h + 1, u);
    28             ver[++indx] = u;
    29             deep[indx] = h;
    30         }
    31     }
    32 }
    33 
    34 void ST(int n){
    35     for(int i = 1; i <= n; i++){
    36         dp[i][0] = i;
    37     }
    38     for(int j = 1; (1 << j) <= n; j++){
    39         for(int i = 1; i + (1 << j) - 1 <= n; i++){
    40             int x = dp[i][j - 1], y = dp[i + (1 << (j - 1))][j -1];
    41             dp[i][j] = deep[x] < deep[y] ? x : y;
    42         }
    43     }
    44 }
    45 
    46 int RMQ(int l, int r){
    47     int len = log2(r - l + 1);
    48     int x = dp[l][len], y = dp[r - (1 << len) + 1][len];
    49     return deep[x] < deep[y] ? x : y;
    50 }
    51 
    52 int LCA(int x, int y){
    53     int l = first[x];
    54     int r = first[y];
    55     if(l > r) swap(l, r);
    56     int pos = RMQ(l, r);
    57     return ver[pos];
    58 }
    59 
    60 void path(int x, int root, int &pos){
    61     while(x != root && x != -1){
    62         yy[pos++] = val[x];
    63         x = pre[x];
    64     }
    65 }
    66 
    67 void solve(int x, int y, int k){
    68     int pos = 0, lca = LCA(x, y);
    69     path(x, lca, pos);
    70     path(y, lca, pos);
    71     yy[pos++] = val[lca];
    72     if(pos < k) puts("invalid request!");
    73     else{
    74         sort(yy, yy + pos, cmp);//注意是从大到小的第 k 大!!!!!!!!!
    75         printf("%d
    ", yy[k - 1]);
    76     }
    77 }
    78 
    79 int main(void){
    80     int n, q, x, y, op;
    81     scanf("%d%d", &n, &q);
    82     for(int i = 1; i <= n; i++){
    83         scanf("%d", &val[i]);
    84     }
    85     for(int i = 1; i < n; i++){
    86         scanf("%d%d", &x, &y);
    87         vt[x].push_back(y);
    88         vt[y].push_back(x);
    89     }
    90     dfs(1, 1, -1);
    91     ST(indx);
    92     while(q--){
    93         scanf("%d%d%d", &op, &x, &y);
    94         if(!op) val[x] = y;
    95         else solve(x, y, op);
    96     }
    97     return 0;
    98 }
    View Code
  • 相关阅读:
    解决调用未定义 swoole_async_readfile函数问题
    7000字 Redis 超详细总结笔记总 | 收藏必备!
    C/C++语言编程修养
    glib 队列
    sprintf 详解
    json 需替换 特殊字符串
    glib 关系
    glib 简介
    gprof 代码效率测量
    glib 树
  • 原文地址:https://www.cnblogs.com/geloutingyu/p/7210643.html
Copyright © 2020-2023  润新知