首页 > 代码库 > HDU 3966 Aragorn's Story --树链剖分
HDU 3966 Aragorn's Story --树链剖分
题意: 树上路径之间的点统一加减k,查询某点的值
解法:不会LCA的解法,于是用树链剖分了,比较简单的剖分,然后用线段树维护就行了,相当于区间更新,单点查询,查询点 i 的值时,只需在线段树中查询pos[u]位置的值即可。
加IO优化900+ms
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <cmath>#include <algorithm>using namespace std;#define N 50007int siz[N]; //子树大小int son[N]; //重儿子int dep[N]; //深度int pos[N]; //在线段树中的位置int Top[N]; //所在重链的祖先int fa[N]; //父节点int head[2*N],tot,POS,n,m,q;struct Edge{ int v,next;}G[2*N];int tree[4*N],mark[4*N],a[N];void init(){ POS = tot = 0; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); memset(tree,0,sizeof(tree)); memset(mark,0,sizeof(mark));}void addedge(int u,int v){ G[tot].v = v, G[tot].next = head[u], head[u] = tot++; G[tot].v = u, G[tot].next = head[v], head[v] = tot++;}void pushdown(int l,int r,int rt){ int mid = (l+r)/2; if(mark[rt]) { mark[2*rt] += mark[rt]; mark[2*rt+1] += mark[rt]; tree[2*rt] += mark[rt]*(mid-l+1); tree[2*rt+1] += mark[rt]*(r-mid); mark[rt] = 0; }}void update(int l,int r,int aa,int bb,int k,int rt){ if(aa <= l && bb >= r) { tree[rt] += k*(r-l+1); mark[rt] += k; return; } int mid = (l+r)/2; if(aa <= mid) update(l,mid,aa,bb,k,2*rt); if(bb > mid) update(mid+1,r,aa,bb,k,2*rt+1);}int query(int l,int r,int pos,int rt){ if(l == r) return tree[rt]; pushdown(l,r,rt); int mid = (l+r)/2; if(pos <= mid) return query(l,mid,pos,2*rt); else return query(mid+1,r,pos,2*rt+1);}void dfs(int u,int f){ dep[u] = dep[f]+1; siz[u] = 1; for(int i=head[u];i!=-1;i=G[i].next) { int v = G[i].v; if(v == f) continue; fa[v] = u; dfs(v,u); if(son[u] == -1 || siz[v] > siz[son[u]]) son[u] = v; siz[u] += siz[v]; }}void dfs2(int u,int father){ pos[u] = ++POS; Top[u] = father; if(son[u] != -1) dfs2(son[u],father); for(int i=head[u];i!=-1;i=G[i].next) { int v = G[i].v; if(v != fa[u] && v != son[u]) dfs2(v,v); }}void Change(int u,int v,int k){ int fx = Top[u], fy = Top[v]; while(fx != fy) { if(dep[fx] < dep[fy]) { swap(u,v); swap(fx,fy); } update(1,POS,pos[fx],pos[u],k,1); u = fa[fx]; fx = Top[u]; } if(dep[u] > dep[v]) swap(u,v); update(1,POS,pos[u],pos[v],k,1);}inline int in(){ char ch; int a = 0; while((ch = getchar()) == ‘ ‘ || ch == ‘\n‘); a += ch - ‘0‘; while((ch = getchar()) != ‘ ‘ && ch != ‘\n‘) { a *= 10; a += ch - ‘0‘; } return a;}int main(){ int u,v,k,i; char ss[5]; while(scanf("%d%d%d",&n,&m,&q)!=EOF) { init(); for(i=1;i<=n;i++) a[i] = in(); for(i=1;i<n;i++) { u = in(), v = in(); addedge(u,v); } dep[0] = 0; dfs(1,0); dfs2(1,1); for(i=1;i<=n;i++) update(1,POS,pos[i],pos[i],a[i],1); while(q--) { scanf("%s",ss); if(ss[0] == ‘Q‘) { u = in(); printf("%d\n",query(1,POS,pos[u],1)); } else { u = in(), v = in(), k = in(); if(ss[0] == ‘I‘) Change(u,v,k); else Change(u,v,-k); } } } return 0;}
HDU 3966 Aragorn's Story --树链剖分
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。