其他分享
首页 > 其他分享> > LCA C 求和 求子树权值和 树上节点单点修改 dfs序+树状数组

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

作者:互联网

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

来源:牛客网

题目描述

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

给定一个根节点 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-1n−1 行每行两个正整数 u,vu,vu,v,表示边的两个端点

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

输出描述:

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

示例1

输入

复制
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
27

备注:

1≤n,m≤1e6,1≤k≤n1\leq n,m\leq 1e6,1\leq k\leq n1≤n,m≤1e6,1≤k≤n 1≤u,v≤n1\leq u,v \leq n1≤u,v≤n 1≤a≤n1\leq a\leq n1≤a≤n −1e6≤vali,x≤1e6−1e6\leq val_i,x\leq 1e6−1e6≤vali​,x≤1e6 建议使用 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;}
/*样例区

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



标签:int,res,ll,cin,dfs,树权值,LCA,节点,define
来源: https://www.cnblogs.com/er007/p/16622928.html