洛谷P3038 [USACO11DEC]牧草种植Grass Planting

时间:2019-11-06
本文章向大家介绍洛谷P3038 [USACO11DEC]牧草种植Grass Planting,主要包括洛谷P3038 [USACO11DEC]牧草种植Grass Planting使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

题目

树链剖分或者树上差分

树链剖分只能对点进行操作,所以把边权化为点权。树上化边权为点权的一般操作是把边权赋到深度较深的点里。

然后用树链剖分+线段树更改权值路径和+单点查询即可解决该问题。

#include <bits/stdc++.h>
#define N 4001011
#define ls l, mid, root << 1
#define rs mid + 1, r, root << 1 | 1
using namespace std;
struct edg {
    int to, nex;
}e[N * 4];
int lin[N], dep[N], fat[N], siz[N], son[N], data[N], dfn[N], top[N], temp[N], cnt, n, m, tot;//data[i]表示i的点权。 
int tree[N << 2], lazy[N << 2];
inline void add(int f, int t)//默认边权为0 
{
    e[++cnt].nex = lin[f];
    e[cnt].to = t;
    lin[f] = cnt;
}
void dfs1(int now, int fa)
{
    dep[now] = dep[fa] + 1;
    fat[now] = fa;
    siz[now] = 1;
    for (int i = lin[now]; i; i = e[i].nex)
    {
        int to = e[i].to;
        if (to == fa) continue;
        dfs1(to, now);
        siz[now] += siz[to];
        if (siz[to] > siz[son[now]])
            son[now] = to;
    }
}
void dfs2(int now, int tes) //求出dfs序, 树链剖分求lca 
{
    dfn[now] = ++tot;//dfn是dfs序
    top[now] = tes;
    if (!son[now]) return;
    dfs2(son[now], tes);
    for (int i = lin[now]; i; i = e[i].nex)//找重链
    {
        int to = e[i].to;
        if (to == fat[now] || to == son[now]) continue;
        dfs2(to, to);
    }
}   
inline void pushup(int root) {tree[root] = tree[root << 1] + tree[root << 1 | 1];}
void build(int l, int r, int root)
{   
    if (l == r)
    {
        tree[root] = 0;
        return;
    }
    int mid = (l + r) >> 1;
    build(ls), build(rs);
    pushup(root);
}   
void pushdown(int l, int r, int root)
{
    int mid = (l + r) >> 1;
    if (lazy[root])
    {
        lazy[root << 1] += lazy[root];
        lazy[root << 1 | 1] += lazy[root];
        tree[root << 1] += lazy[root] * (mid - l + 1);
        tree[root << 1 | 1] += lazy[root] * (r - mid);
        lazy[root] = 0;
    }
}
int query(int pos, int l, int r, int root)
{
    if (l == r)    
        return tree[root];
    int res = 0, mid = (l + r) >> 1;
    pushdown(l, r, root);
    if (pos <= mid)
        res += query(pos, ls);
    else  
        res += query(pos, rs);
    return res;
}
void update(int ql, int qr, int add, int l, int r, int root)
{
    if (ql <= l && r <= qr)
    {
        tree[root] += (r - l + 1) * add;
        lazy[root] += add;
        return;
    }
    pushdown(l, r, root);
    int mid = (l + r) >> 1;
    if (ql <= mid)
        update(ql, qr, add, ls);
    if (qr > mid)
        update(ql, qr, add, rs);
    pushup(root);
}
void U(int x, int y)
{
    while (top[x] != top[y])//找他们的lca
    {
        if (dep[top[x]] < dep[top[y]]) swap(x, y);
        update(dfn[top[x]], dfn[x], 1, 1, n, 1);
        x = fat[top[x]];
    }
    if (dep[x] > dep[y])
        swap(x, y);
    update(dfn[x] + 1, dfn[y], 1, 1, n, 1);
}
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1, a, b; i < n; i++) {scanf("%d%d", &a, &b), add(a, b), add(b, a);}
    dfs1(1, 0);
    dfs2(1, 1);
    build(1, n, 1);
    while (m--)
    {
        char flag; int a, b;
        cin >> flag >> a >> b;
        if (flag == 'P')
            U(a, b);
        else
        {
            if (dep[a] < dep[b]) swap(a, b);
            printf("%d\n", query(dfn[a], 1, n, 1));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/liuwenyao/p/11804051.html