[CodeForces 593D]Happy Tree Party[LCA][路径压缩]

原创 2015年11月21日 10:44:03
题目链接:[CodeForces 593D]Happy Tree Party[LCA][路径压缩]

题意分析:

给出两个操作,1和2。

1代表查询结点a到结点b之间最短路径,将路径上的权值对y进行向下求整,输出结果。

2更改某个结点的权值

解题思路:

y最大1e18,对于除数为大于1的数字来说,最多除60次就可以让y变成0了。所以用lca不断除,当结果是0时就返回结果。

不过还要考虑除数为1的情况,这就会使得路径变得很长导致T了。所以要路径压缩一下。

个人感受:

比赛的时候知道LCA,但是觉得会T,没考虑过向下除不超过60次就变0了。

具体代码如下:

#include<cstdio>
#include<iostream>
#include<queue>
#define ll long long
#define pr(x) cout << #x << " = " << (x) << '\n';
using namespace std;

const int INF = 0x7f7f7f7f;
const int MAXN = 2e5 + 111;

struct Node{
    int v, id;
    ll w;
    Node(int _v, ll _w, int _id): v(_v), w(_w), id(_id) {}
};

int dep[MAXN], fa[MAXN], par[MAXN], point[MAXN]; // point:点所对应的边id
ll val[2 * MAXN];
vector<Node> G[MAXN];

int find(int x)
{
    return x == par[x] ? x : par[x] = find(par[x]);
}

void dfs(int u, int p, int d)
{
    dep[u] = d;
    fa[u] = p;
    for (int i = 0; i < G[u].size(); ++i)
    {
        Node &e = G[u][i];
        if (e.v != p)
        {
            val[e.v] = e.w; // 将点所对应的权值转换为以这个结点为结尾的边对应的权值来记录
            point[e.id] = e.v; // 用id来查找点
            dfs(e.v, u, d + 1);
        }
    }
}

ll lca(int u, int v, ll w)
{
    u = find(u), v = find(v);
    while (u != v) // 每次将较低的结点向上提升,不断除
    {
        if (dep[u] < dep[v]) swap(u, v);
        w /= val[u]; u = find(fa[u]);
        if (w == 0) return 0;
    }
    return w;
}

void update(int u) // 如果该点权值为一,那么就让它的祖先指向它的父亲结点
{
    par[u] = fa[u];
}

int main()
{
    int n, m, u, v, op;
    ll w;
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) G[i].clear(), par[i] = i;
    for (int i = 1; i < n; ++i)
    {
        scanf("%d%d%I64d", &u, &v, &w);
        G[u].push_back(Node(v, w, i));
        G[v].push_back(Node(u, w, i));
    }

    dfs(1, -1, 0);

    for (int i = 2; i <= n; ++i) if (val[i] == 1) update(i);

    int a, b, p;
    ll y, c;
    while (m --)
    {
        scanf("%d", &op);
        if (op == 1)
        {
            scanf("%d%d%I64d", &a, &b, &y);
            printf("%I64d\n", lca(a, b, y));
        }
        else
        {
            scanf("%d%I64d", &p, &c);
            int v = point[p]; val[v] = c;
            if (c == 1) update(v);
        }
    }
    return 0;
}


版权声明:欢迎转载(^ω^)~不过转载请注明原文出处:http://blog.csdn.net/catglory ლ(╹◡╹ლ)

相关文章推荐

LCA+最小生成树 Codeforces609E Minimum spanning tree for each edge

传送门:点击打开链接 题意:给一个图,有m条边n个点,如果对于一个最小生成树中要求必须包括第i条边,那么最小生成树的权值总和最小是多少 思路:求出最小生成树,然后对于m条边相当于m次查询,每次查询...

codeforces 593D(并查集 + LCA)

题意不在描述. 首先我们注意到改变每个点的值时,只会变的更小,每次要除的数为1e18 , 由于log2(1e18) <= 60 .那么最多只需要除以至多60次大于等于2的数变回变成0,所以我们 只...

Codeforces 593D - Happy Tree Party(树链剖分)

#include #include #include #include #include #define lson l, m, rt

【Codeforces Round 329 (Div 2) D】【LCA+并查集路径压缩】Happy Tree Party 除上两点间路径全部权值

#include #include #include #include #include #include #include #include #include #include #include #...

CodeForces 593D Happy Tree Party(树链剖分(边权) or LCA+并查集)

题意:给你一棵数,n个点n-1条边,每条边有个权值,q次询问,询问有两种: 1 a b y : a到b的路径上不断进行y = y/xi(像下取整),问最后y的值 2 p c :  将第p条边的权值改为...
  • CillyB
  • CillyB
  • 2017年08月09日 01:32
  • 186

codeforces 593D Happy Tree Party Lca+并查集

codeforces 593D Happy Tree Party Lca+并查集
  • wzq_QwQ
  • wzq_QwQ
  • 2015年11月06日 07:38
  • 729

LCA + 并查集 Happy Tree Party codeforces593D

一个64位的数,最多在被大于1的数整除64次后就变为0 所以对于每次访问,我们最多除64次 那么我们就要将为1的路压缩,使用并查集 每次访问使用lca,找到公共祖先lc,然后u->lc,v->lc,访...

codeforces 593 D. Happy Tree Party (LCA + 并查集)

D. Happy Tree Party time limit per test 3 seconds memory limit per test 256 megabytes ...
  • whai362
  • whai362
  • 2015年11月05日 20:30
  • 489

【13.91%】【codeforces 593D】Happy Tree Party

time limit per test3 seconds memory limit per test256 megabytes inputstandard input outputstandar...

Codeforces Round #329 (Div. 2) 593D. Happy Tree Party(树链剖分)

题意:给你一棵树,每条边上有权值。有两个操作 1. u v p 从u~v的路径上用p除每跳边的权值,向下取整 2. u p 将第u条边的权值改为p 思路:树链剖分 呃…算是模板题吧 因为这道...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:[CodeForces 593D]Happy Tree Party[LCA][路径压缩]
举报原因:
原因补充:

(最多只允许输入30个字)