Luo Gu P3178 [HAOI] 2015 tree operation

topic

Sectional title bare trees, this problem may be more profound understanding of the tree section to convert the tree node for the range of thought.

To be noted that the interval in successive node, must be in a subtree.

#include <bits/stdc++.h>
#define int long long 
#define ls left, mid, root << 1
#define rs mid + 1, right, root << 1 | 1
#define N 600100    
using namespace std;
int n, m, rot, mod, tot, cnt;   
int data[N], id[N], dep[N], size[N], lin[N], ans[N * 8], lazy[N * 8], dp[N], fa[N], top[N], son[N];
struct edg {
    int to, nex;
} e[N];
inline void add(int f, int t)
{
    e[++cnt].to = t;
    e[cnt].nex = lin[f];
    lin[f] = cnt;
}           
inline void pushup(int root)
{
    ans[root] = (ans[root << 1] + ans[root << 1 | 1]);
}    
inline void pushdown(int root, int left, int right)
{ 
    int mid = (left + right) >> 1;
    if (lazy[root])
    {
        ans[root << 1] += (mid - left + 1) * lazy[root];
        ans[root << 1];
        ans[root << 1 | 1] += (right - mid) * lazy[root];
        ans[root << 1 | 1];
        lazy[root << 1] += lazy[root]; 
        lazy[root << 1 | 1] += lazy[root];
        lazy[root] = 0; 
    }
}
void build(int left, int right, int root)
{
    if (left == right)
    {   
        ans[root] = dp[left], ans[root];
        return;     
    }               
    int mid = (left + right) >> 1;
    build(ls), build(rs);
    pushup(root);   
}                   
inline void update(int left, int right, int root, int add, int ql, int qr)
{   
    if (left >= ql && right <= qr)
    {
        ans[root] += (right - left + 1) * add;
        lazy[root] += add;     
        ans[root];
        return;                
    }                          
    int mid = (left + right) >> 1;
    pushdown(root, left, right);//线段树的pushdown操作是为了弥补之前没向下传递标记的坑。 
    if (ql <= mid)              
        update(ls, add, ql, qr);
    if (qr > mid)               
        update(rs, add, ql, qr);
    pushup(root);               
}   
inline int query(int left, int right, int root, int ql, int qr)
{
    int res = 0;
    if (left >= ql && right <= qr)
        return ans[root];
    int mid = (left + right) >> 1;
    pushdown(root, left, right);
    if (ql <= mid)
        res = ( res + query(ls, ql, qr) );
    if (qr > mid)
        res = res + query(rs, ql, qr) ;
    return res;
}
void dfs1(int now, int f, int de)
{   
    fa[now] = f, dep[now] = de, size[now] = 1;
    int maxsize = -1;
    for (int i = lin[now]; i; i = e[i].nex)
    {
        if (e[i].to == f) continue;
        dfs1(e[i].to, now, de + 1);
        size[now] += size[e[i].to];
        if (size[e[i].to] > maxsize)
        {
            maxsize = size[e[i].to];
            son[now] = e[i].to;
        }
    }
}   
void ulca(int x, int y, int z)
{
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]])
            swap(x, y);
        update(1, n, 1, z, id[top[x]], id[x]);
        x = fa[top[x]];
    }
    if (dep[x] > dep[y])
        swap(x, y);
    update(1, n, 1, z, id[x], id[y]); 
}
int qlca(int x, int y)
{
    int res = 0;
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]])
            swap(x, y);
        res = ( res + query(1, n, 1, id[top[x]], id[x]) );
        x = fa[top[x]];
    }
    if (dep[x] > dep[y])
        swap(x, y);
    res = ( res + query(1, n, 1, id[x], id[y]) );
    return res;
}
void upd(int x, int y) 
{
    update(1, n, 1, y, id[x], id[x] + size[x] - 1);
}
int que(int x) 
{
    return query(1, n, 1, id[x], id[x] + size[x] - 1);
}
void dfs2(int now, int t)
{
    top[now] = t;
    dp[++tot] = data[now];
    id[now] = tot;
    if (!son[now])
        return;
    dfs2(son[now], t);
    for (int i = lin[now]; i; i = e[i].nex)
    {
        int to = e[i].to;
        if (to != fa[now] && to != son[now])
            dfs2(to, to);
    }
}
signed main()
{
    scanf("%lld%lld", &n, &m);
    rot = 1;
    for (int i = 1; i <= n; i++)
            scanf("%lld", &data[i]); 
    for (int i = 1; i < n; i++)
    {
        int a, b;
        scanf("%lld%lld", &a, &b);
        add(a, b);
        add(b, a);
    }
    dfs1(rot, 0, 1);
    dfs2(rot, rot);
    build(1, n, 1); 
    for (int i = 1; i <= m; i++)
    {   
        int flag;
        scanf("%lld", &flag);
        if (flag == 1)
        {
            int x, a;
            scanf("%lld%lld", &x, &a);
            update(1, n, 1, a, id[x], id[x]);
        }
        if (flag == 2)
        {
            int x, a;
            scanf("%lld%lld", &x, &a);
            update(1, n, 1, a, id[x],  id[x] + size[x] - 1);
        }
        if (flag == 3)
        {
            int a;
            scanf("%lld", &a);
            printf("%lld\n", qlca(1, a));//不能写成id[1],id[a]因为id子树之间是连续的,所以a到1之间并不是连续边号。 
        }
    }   
    return 0;
}
/*
5 5 2 24
7 3 7 8 0 
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
*/

Guess you like

Origin www.cnblogs.com/liuwenyao/p/11229609.html