LCA C求和 求子树权值和 树上节点单点修改 dfs序+树状数组

链接:https://ac.nowcoder.com/acm/problem/204871

来源:牛客网

题目描述

已知有nnn 个节点,有n−1n-1n1 条边,形成一个树的结构。

给定一个根节点 kkk,每个节点都有一个权值,节点i的权值为 viv_ivi

mmm 个操作,操作有两种类型:

1 a x :表示将节点aaa 的权值加上xxx

2 a :表示求aaa 节点的子树上所有节点的和(包括aaa 节点本身)

输入描述:

第一行给出三个正整数 n,m,kn,m,kn,m,k,表示树的节点数、操作次数、和这棵树的根节点.

第二行给出nnn 个正整数,第iii 个正整数表示第 iii个节点的权值valival_ivali

下面 n−1n-1n1行每行两个正整数 u,vu,vu,v,表示边的两个端点

接下来mmm 行,每行给出一个操作

输出描述:

对于每个类型为 2 的操作,输出一行一个正整数,表示以aaa 为根的子树的所有节点的权值和

示例1

输入

复制 5 6 1<br /> 1 2 3 4 5<br /> 1 3<br /> 1 2<br /> 2 4<br /> 2 5<br /> 1 2 10<br /> 1 3 10<br /> 1 4 5<br /> 1 5 1<br /> 2 3<br /> 2 2

5 6 1
1 2 3 4 5
1 3
1 2
2 4
2 5
1 2 10
1 3 10
1 4 5
1 5 1
2 3
2 2

输出

复制 13<br /> 27

13
27

备注:

1≤n,m≤1e6,1≤k≤n1\leq n,m\leq 1e6,1\leq k\leq n1n,m1e6,1kn
1≤u,v≤n1\leq u,v \leq n1u,vn
1≤a≤n1\leq a\leq n1an
−1e6≤vali,x≤1e6−1e6\leq val_i,x\leq 1e61e6vali,x1e6
建议使用 scanf 读入

分析

欧拉序:每经过一次该节点记录一次该序列

dfs序:记录入栈和出栈的序列

dfn序:只记录入栈的序列

用dfs序,记录每个点入栈是什么时间 l[u] = ++time,出栈是什么时间r[u] = time

在这个时间之内的就是它的子树

用树状数组维护区间和

如果 u 的子树增加了x,在[l[u],r[u]]内的区间和也要增加 x

所以直接把x 增加在 l[u] 位置或者 r[u] 位置就可以了

询问 u 子树的权值和就是 query(r[u]) - query(l[u]-1)

//-------------------------代码----------------------------

//#define int ll
const int N = 2e6+10;
int n,m,k;
int e[N],ne[N],w[N],h[N],idx,v[N];
void add1(int a,int b) {
    e[idx] = b,ne[idx] = h[a],h[a] = idx ++ ;
}

ll tr[N];
int l[N],r[N],num;

void add(int x,int v) {
    for(;x<=n;x+=lowbit(x)) {tr[x] += v;}
}

ll sum(int x) {
    ll res = 0;for(;x;x-=lowbit(x)) res += tr[x];return res;
}

void dfs(int u,int fa) {
    l[u] = ++ num;
    fe(i,u) {
        if(e[i] != fa) {
            dfs(e[i],u);
        }
    }
    r[u] = num;
}

void solve()
{
    ms(h,-1);
    cin>>n>>m>>k;
    fo(i,1,n) {
        cin>>v[i];
    }
    fo(i,1,n-1) {
        int x,y;cin>>x>>y;
        add1(x,y);add1(y,x);
    }
    dfs(k,0);
    fo(i,1,n) add(l[i],v[i]);
    while(m -- ) {
        int op;cin>>op;
        if(op == 1) {
            int a,x;cin>>a>>x;
            add(l[a],x);
        } else {
            int x;cin>>x;
            cout<<sum(r[x]) - sum(l[x] - 1)<<endl;
        }
    }
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

#include<bits/stdc++.h>#define TLE ios::sync_with_stdio(0),cin.tie(0)#define endl "\n"#define FILE "a"#define pb push_back#define gg exit(0);#define rt return;#define bd cout<<"debug"<<endl;#define db(x) cout<<#x<<':'<<x<<endl;#define dbb(i,a) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<endl;#define dbbb(i,a,b) cout<<#i<<':'<<i<<' '<<#a<<':'<<a<<' '<<#b<<':'<<b<<endl;#define TIME cout<<"RuningTime: "<<clock()<<"ms\n";#define YES cout<<"YES"<<endl;#define Yes cout<<"Yes"<<endl;#define NO cout<<"NO"<<endl;#define No cout<<"No"<<endl;#define None cout<<-1<<endl;#define el cout<<endl;#define x first#define y second#define V vector#define fo(i,j,n) for(int i = j;i<=n;i++)#define of(i,n,j) for(int i = n;i>=j;i--)#define fe(i,u) for(int i = h[u];~i;i=ne[i])#define all(a) a.begin(),a.end()#define alll(a) a.begin()+1,a.end()#define ms(a,b) memset(a, b, sizeof(a));#define tr_len(u) (tr[u].r - tr[u].l + 1)#define tr_mid (tr[u].l + tr[u].r >> 1)#define ul (u<<1)#define ur (u<<1|1)#define lowbit(x) (x&-x)#define gcd(a,b) __gcd(a,b)#define CLAP 11243using namespace std;void clapping() {#if CLAP == 1srand(time(NULL)+rand());freopen("a.in","r",stdin);freopen("a.out","w",stdout);//freopen("a.in","w",stdout);#endif}template<class T>inline void read(T &res) { char c;T flag = 1; while((c = getchar()) < '0' || c > '9') if(c == '-') flag = -1;res = c - '0'; while((c=getchar())>='0'&&c<='9')res=(res<<1)+(res<<3)+(c^48);res*=flag;}typedef pair<int,int> pii;typedef pair<long,long>pll;typedef long long ll;const int inf = 0x3f3f3f3f;const ll INF = 0x3f3f3f3f3f3f3f3fll;const double eps = 1e-8;int dy[] = {1,0,-1,0,1,1,-1,-1};int dx[] = {0,1,0,-1,1,-1,1,-1};ll qmi(ll a,ll b) {int res = 1;for(;b;b>>=1,a = a * a ) {if(b&1) res = res * a;}return res;}template<class T> T exgcd(T a,T b,T &x,T &y) {if(b == 0) {x = 1;y = 0;return a;}ll d = gcd_ed(b,a%b,y,x);y = y - a / b * x;return d;}template<class T> T qmul(T a,T b,T p) {T res = 0;for(;b;b >>= 1,a = (a + a) % p) {res = (res + a) % p;}return res;}/*文档区

*/void AC(){ //// _oo0oo_// o8888888o// 88" . "88// (| -_- |)// 0\ = /0// ___/`---'\___// .' \\| |// '.// / \\||| : |||// \// / _||||| -:- |||||- \// | | \\\ - /// | |// | \_| ''\---/'' |_/ |// \ .-\__ '-' ___/-. /// ___'. .' /--.--\ `. .'___// ."" '< `.___\_<|>_/___.' >' "".// | | : `- \`.;`\ _ /`;.`/ - ` : | |// \ \ `_. \_ __\ /__ _/ .-` / /// =====`-.____`.___ \_____/___.-`___.-'=====// 佛祖保佑, 永无bug;}

//-------------------------代码----------------------------
//#define int llconst int N = 2e6+10;int n,m,k;int e[N],ne[N],w[N],h[N],idx,v[N];void add1(int a,int b) { e[idx] = b,ne[idx] = h[a],h[a] = idx ++ ;}
ll tr[N];int l[N],r[N],num;
void add(int x,int v) { for(;x<=n;x+=lowbit(x)) {tr[x] += v;}}
ll sum(int x) { ll res = 0;for(;x;x-=lowbit(x)) res += tr[x];return res;}
void dfs(int u,int fa) { l[u] = ++ num; fe(i,u) { if(e[i] != fa) { dfs(e[i],u); } } r[u] = num;}
void solve(){ ms(h,-1); cin>>n>>m>>k; fo(i,1,n) { cin>>v[i]; } fo(i,1,n-1) { int x,y;cin>>x>>y; add1(x,y);add1(y,x); } dfs(k,0); fo(i,1,n) add(l[i],v[i]); while(m -- ) { int op;cin>>op; if(op == 1) { int a,x;cin>>a>>x; add(l[a],x); } else { int x;cin>>x; cout<<sum(r[x]) - sum(l[x] - 1)<<endl; } }}void main_init() {}signed main(){AC();clapping();TLE;cout<<fixed<<setprecision(12);main_init();// while(cin>>n,n)// while(cin>>n>>m,n,m)//int t;cin>>t;while(t -- )solve();//{solve(); }return 0;}
/*样例区

*/
//------------------------------------------------------------

你可能想看:
分享给朋友: