loj10139. 「一本通 4.5 练习 1」树上操作(loj2125. 「HAOI2015」树上操作 )

Posted junk-yao-blog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了loj10139. 「一本通 4.5 练习 1」树上操作(loj2125. 「HAOI2015」树上操作 )相关的知识,希望对你有一定的参考价值。

思路:

  第二遍dfs时记录end[x]为在结点序列中以x为根的子树最后访问的节点,写个线段树标记下传即可。与值有关的数据注意long long

#include<cstdio>
#include<iostream>
#include<vector>
#include<cmath>
#include<string>
using namespace std;
const int maxn = 100010;
inline void qread(int &x){
    x = 0;
    register int ch = getchar(), flag = 0;
    while(ch < 0 || ch > 9)    {
        if(ch == -)    flag = 1;
        ch = getchar();
    }
    while(ch >= 0 && ch <= 9)
        x = 10 * x + ch - 48, ch = getchar();
    if(flag)    x = -x;    
}
int n, m, rt = 1;
int val[maxn];
int head[maxn];
int go[maxn << 1];
int nxt[maxn << 1];

int f[maxn];
int deep[maxn];
int size[maxn];
int son[maxn];
int top[maxn];
int seg[maxn];
int rev[maxn];
int end[maxn];
long long cov[maxn << 2];
long long sum[maxn << 2];
long long SUM;
inline void init(){
    qread(n);        qread(m);
    for(int i=1; i<=n; ++i)
        qread(val[i]);
    for(register int i=1; i<n; ++i){
        register int x, y;
        qread(x), qread(y);
        go[i] = y;
        go[i + n] = x;
        nxt[i] = head[x];
        head[x] = i;
        nxt[i + n] = head[y];
        head[y] = i + n;
    }
    deep[rt] = 1;
    seg[0] = seg[1] = rev[1] = top[1] = 1;
}
void dfs1(int x){
    size[x] = 1;
    for(register int i = head[x]; i; i = nxt[i])
        if(!deep[go[i]]){
            f[go[i]] = x;
            deep[go[i]] = deep[x] + 1;
            dfs1(go[i]);
            size[x] += size[go[i]];
            if(size[go[i]] > size[son[x]])
                son[x] = go[i];
        }    
}
void dfs2(int x){
    end[x] = x;
    if(son[x]){
        seg[son[x]] = ++seg[0];
        top[son[x]] = top[x];
        rev[seg[0]] = son[x];
        dfs2(son[x]);
        end[x] = end[son[x]];
    }
    for(register int i = head[x]; i; i = nxt[i]){
        if(!top[go[i]]){
            seg[go[i]] = ++seg[0];
            rev[seg[0]] = go[i];
            top[go[i]] = go[i];
            dfs2(go[i]);
            end[x] = end[go[i]];
        }
    }
}
inline void pushdown(int x, int t){
    cov[x << 1] += cov[x];
    cov[x << 1 | 1] += cov[x];
    sum[x << 1] += cov[x] * ((t + 1) >> 1);
    sum[x << 1 | 1] += cov[x] * (t >> 1);
    cov[x] = 0;
}
void segbuild(int l, int r, int x){
    if(l==r){
        sum[x] = val[rev[l]];
        return ;
    }
    int mid = (l + r) >> 1;
    segbuild(l, mid, x << 1);
    segbuild(mid + 1, r, x << 1 | 1);
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
} 
void segadd(int l, int r, int L, int R, long long v, int x){
    if(L <= l && R >= r){
        cov[x] += v;
        sum[x] += v * (r - l + 1);
        return ;
    }
    pushdown(x, r - l + 1);
    int mid = (l + r) >> 1;
    if(mid >= L)    segadd(l, mid, L, R, v, x << 1);
    if(mid < R)        segadd(mid + 1, r, L, R, v, x << 1 | 1);
    sum[x] = sum[x << 1] + sum[x << 1 | 1];
}
void segquery(int l, int r, int L, int R, int x){
    if(L <= l && R >= r){
        SUM += sum[x];
        return ;
    }
    pushdown(x, r - l + 1);    
    int mid = (l + r) >> 1;
    if(mid >= L)    segquery(l, mid, L, R, x << 1);
    if(mid < R)        segquery(mid + 1, r, L, R,  x << 1 | 1);
}
void treeask(int x, int y){
    int fx = top[x], fy = top[y];
    while(fx != fy){
        if(deep[fx] < deep[fy])    swap(x, y), swap(fx, fy);
        segquery(1, seg[0], seg[fx], seg[x], 1);
        x = f[fx];
        fx = top[x];
    }
    if(deep[x] > deep[y])    swap(x, y);
    segquery(1, seg[0], seg[x], seg[y], 1); 
}
int main(void){
    freopen("data6.in.txt", "r", stdin);
    freopen("data6my.txt", "w", stdout);
    init();
    dfs1(rt);
    dfs2(rt);
    segbuild(1, seg[0], 1);
    while(m--){
        int op;
        qread(op);
        if(op == 1){
            int x, a;
            qread(x), qread(a);
            segadd(1, seg[0], seg[x], seg[x], a, 1);
        }
        else if(op == 2){
            int x, a;
            qread(x), qread(a);
            segadd(1, seg[0], seg[x], seg[end[x]], a, 1);
        }
        else{
            int x;
            qread(x);
            SUM = 0;
            treeask(rt, x);
            printf("%lld
", SUM);
        }
    }
}

 

以上是关于loj10139. 「一本通 4.5 练习 1」树上操作(loj2125. 「HAOI2015」树上操作 )的主要内容,如果未能解决你的问题,请参考以下文章

loj10195. 「一本通 6.1 练习 2」转圈游戏 (loj2608)

loj10188. 「一本通 5.6 练习 1」玩具装箱

loj10150. 「一本通 5.1 练习 1」括号配对

loj10144. 「一本通 4.6 练习 1」宠物收养所

loj10194. 「一本通 6.1 练习 1」A 的 B 次方

loj #10134. 「一本通 4.4 练习 1」Dis