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