HDU - 3078 Network(暴力+LCA)

来源:互联网 发布:vx交友软件 编辑:程序博客网 时间:2024/04/29 09:06

题目大意:给出n个点的权值,m条边,2种操作
0 u num,将第u个点的权值改成num
k u v,询问u到v这条路上第k大的权值点

解题思路:该点的话直接该,找第k大的话直接暴力

#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 80010#define M 160010struct Edge{    int to, next, val;}E[M];int head[N], val[N], depth[M], ver[M], first[M], dis[M], dp[M][62], pre[N];int tot, n, m;bool vis[N];void AddEdge(int u, int v) {    E[tot].to = v; E[tot].next = head[u]; E[tot].val = 1; head[u] = tot++;    u = u ^ v; v = u ^ v; u = u ^ v;    E[tot].to = v; E[tot].next = head[u]; E[tot].val = 1; head[u] = tot++;}void init() {    for (int i = 1; i <= n; i++)        scanf("%d", &val[i]);    int u, v;    memset(head, -1, sizeof(head));    tot = 0;    for (int i = 1; i < n; i++) {        scanf("%d%d", &u, &v);        AddEdge(u, v);    }}void dfs(int u, int dep) {    vis[u] = true; ver[++tot] = u; first[u] = tot; depth[tot] = dep;    for (int i = head[u]; ~i; i = E[i].next) {        int v = E[i].to;        if (!vis[v]) {            dis[v] = dis[u] + E[i].val;            pre[v] = u;            dfs(v, dep+1);            ver[++tot] = u; depth[tot] = dep;        }    }} void RMQ() {    for (int i = 1; i <= tot; i++)        dp[i][0] = i;    int a, b;    for (int j = 1; (1 << j) <= tot; j++)        for (int i = 1; i + (1 << j) - 1 <= tot; i++) {            a = dp[i][j - 1];            b = dp[i + (1 << (j - 1))][j - 1];            if (depth[a] < depth[b])                dp[i][j] = a;            else                dp[i][j] = b;        }}int Query(int x, int y) {    int k = 0;    while (1 << (k + 1) <= (y - x + 1)) k++;    int a = dp[x][k];    int b = dp[y - (1 << k) + 1][k];    if (depth[a] < depth[b])        return a;    return b;}int LCA(int a, int b) {    a = first[a];    b = first[b];    if (a > b) {        a = a ^ b; b = a ^ b; a = a ^ b;    }    int c = Query(a, b);    return ver[c];}int num[N], cnt;void path(int a, int lca) {    int t = a;    while (t != lca) {        num[cnt++] = val[t];        t = pre[t];    }}bool cmp(const int a, const int b) {    return a > b;}void find(int k, int a, int b) {    int lca = LCA(a,b);    if (dis[a] + dis[b] - 2 * dis[lca] + 1 < k) {        printf("invalid request!\n");        return ;    }    else {        cnt = 0;        path(a, lca);        path(b, lca);        num[cnt++] = val[lca];        sort(num, num + cnt, cmp);        printf("%d\n", num[k - 1]);    }}void solve() {    memset(vis, 0, sizeof(vis));    tot = 0;    dis[1] = 0;    pre[1] = 1;    dfs(1,1);    RMQ();    int k, a, b;    while (m--) {        scanf("%d%d%d", &k, &a, &b);        if (!k) {            val[a]=  b;        }        else {            find(k, a, b);        }    }}int main() {    while (scanf("%d%d", &n, &m) != EOF) {        init();        solve();    }    return 0;}
0 0
原创粉丝点击