hdu 3966( 树链剖分+点权更新)
生活随笔
收集整理的這篇文章主要介紹了
hdu 3966( 树链剖分+点权更新)
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
題意:給一棵樹,并給定各個(gè)點(diǎn)權(quán)的值,然后有3種操作:
I C1 C2 K: 把C1與C2的路徑上的所有點(diǎn)權(quán)值加上K
D C1 C2 K:把C1與C2的路徑上的所有點(diǎn)權(quán)值減去K
Q C:查詢節(jié)點(diǎn)編號(hào)為C的權(quán)值
解題思路:這道題是明顯的樹鏈剖分問題,只是這里是點(diǎn)權(quán)更新,注意與邊權(quán)更新的不同,剩下的基本是模板了。
#include<iostream> #include<cstdio> #include<cstring> using namespace std;const int maxn = 50010; struct Segment {int l,r,sum,lazy; }tree[maxn<<2]; struct Edge {int to,next; }edge[maxn<<1]; int n,m,p,cnt,num,pre[maxn],A[maxn]; int top[maxn],son[maxn],size[maxn]; int fa[maxn],idx[maxn],dep[maxn];void addedge(int u,int v) {edge[cnt].to = v;edge[cnt].next = pre[u];pre[u] = cnt++; }void dfs(int u) {size[u] = 1; son[u] = 0;int tmp = 0;for(int i = pre[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(fa[u] == v) continue;fa[v] = u;dep[v] = dep[u] + 1;dfs(v);size[u] += size[v];if(size[v] > tmp){tmp = size[v];son[u] = v;}} }void build_tree(int u,int tp) {idx[u] = ++num; top[u] = tp;if(son[u] != 0) build_tree(son[u],tp);for(int i = pre[u]; i != -1; i = edge[i].next){int v = edge[i].to;if(fa[u] == v || son[u] == v) continue;build_tree(v,v);} }void build_Segment(int rt,int l,int r) {tree[rt].l = l, tree[rt].r = r;tree[rt].sum = tree[rt].lazy = 0;if(l == r) return;int mid = (l + r) >> 1;build_Segment(rt<<1,l,mid);build_Segment(rt<<1|1,mid+1,r); }void PushDown(int rt) {if(tree[rt].lazy != 0){tree[rt<<1].lazy += tree[rt].lazy;tree[rt<<1].sum += tree[rt].lazy;tree[rt<<1|1].lazy += tree[rt].lazy;tree[rt<<1|1].sum += tree[rt].lazy;tree[rt].lazy = 0;} }void PushUp(int rt) {tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum; }void update(int rt,int l,int r,int val) {if(l <= tree[rt].l && tree[rt].r <= r){tree[rt].sum += val;tree[rt].lazy += val;return;}PushDown(rt);int mid = (tree[rt].l + tree[rt].r) >> 1;if(l <= mid) update(rt<<1,l,r,val);if(mid < r) update(rt<<1|1,l,r,val);PushUp(rt); }int query(int rt,int pos) {if(tree[rt].l == tree[rt].r)return tree[rt].sum;PushDown(rt);int mid = (tree[rt].l + tree[rt].r) >> 1;if(pos <= mid) return query(rt<<1,pos);else return query(rt<<1|1,pos); }void Modify(int a,int b,int val) {int f1 = top[a], f2 = top[b];while(f1 != f2){if(dep[f1] < dep[f2]){swap(f1,f2);swap(a,b);}update(1,idx[f1],idx[a],val);a = fa[f1], f1 = top[a];}if(dep[a] > dep[b]) swap(a,b);update(1,idx[a],idx[b],val); }int main() {int u,v,val;char op[2];while(scanf("%d%d%d",&n,&m,&p)!=EOF){memset(pre,-1,sizeof(pre));cnt = num = 0;dep[1] = 0;for(int i = 1; i <= n; i++)scanf("%d",&A[i]);for(int i = 1; i <= m; i++){scanf("%d%d",&u,&v);addedge(u,v);addedge(v,u);}dfs(1);build_tree(1,1);build_Segment(1,1,num);for(int i = 1; i <= n; i++)update(1,idx[i],idx[i],A[i]);while(p--){getchar();scanf("%s",op);if(op[0] == 'I'){scanf("%d%d%d",&u,&v,&val);Modify(u,v,val);}else if(op[0] == 'D'){scanf("%d%d%d",&u,&v,&val);Modify(u,v,-val);}else{scanf("%d",&u);printf("%d\n",query(1,idx[u]));}}}return 0; }
總結(jié)
以上是生活随笔為你收集整理的hdu 3966( 树链剖分+点权更新)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 大数据幽默解释
- 下一篇: 【插件发布】JAVA微服务框架,Jeec