标签:val int tr tree dfs st cf383 ed Propagating
题意:
给定一棵树,带点权。两种询问:
1 x val:节点 x 加上 val,x 的所有儿子减去 val,x 的所有孙子加上 val,以此类推直到叶子
2 x:输出 x 节点的点权
思路:
维护子树的点权:dfs序把树映射为数组
一层加、一层减:开两个树状数组,\(tr[0]\) 维护在原树中的深度为偶的点,其中深度为奇的无意义;\(tr[1]\) 维护在原树中的深度为奇的点,其中深度为偶的无意义
区间加、单点查询:树状数组维护差分
const signed N = 3 + 2e5;
int n, q, a[N]; vector<int> G[N];
//从st[u]到ed[u]是u的子树
int st[N], ed[N], idx; bool t[N]; //0偶层,1奇层
void dfs(int u, int fa, bool dep) {
st[u] = ++idx; t[u] = dep; //记录节点深度奇偶性
for(int v : G[u]) if(v != fa)
dfs(v, u, !dep);
ed[u] = idx;
}
ll tr[2][N]; //0偶BIT,1奇BIT
void sol() {
cin >> n >> q;
for(int i = 1; i <= n; i++) cin >> a[i];
for(int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
G[x].pb(y), G[y].pb(x);
}
dfs(1, 0, 1);
for(int i = 1; i <= n; i++) //维护的是差分
add(tr[t[i]], st[i], a[i]), add(tr[t[i]], st[i]+1, -a[i]);
while(q--) {
int op, x, val; cin >> op >> x;
if(op == 1) {
cin >> val;
add(tr[t[x]], st[x], val), add(tr[t[x]], ed[x]+1, -val);
add(tr[!t[x]], st[x], -val), add(tr[!t[x]], ed[x]+1, val);
}
else cout << ask(tr[t[x]], st[x]) << endl;
}
}
标签:val,int,tr,tree,dfs,st,cf383,ed,Propagating 来源: https://www.cnblogs.com/wushansinger/p/16372904.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。