bzoj 2836: 魔法树(树链剖分)
2016-05-11 19:22
531 查看
2836: 魔法树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 247 Solved: 96
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
40 1
1 2
2 3
4
Add 1 3 1
Query 0
Query 1
Query 2
Sample Output
33
2
HINT
Source
[Submit][Status][Discuss]
题解:dfs序+树链剖分
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 200003 #define LL long long using namespace std; int n,m,t,tot,sz; LL tr[N*4],delta[N*4]; int point ,next ,v ,belong ,size ,son ,fa ,deep ; int pos ,l ,r ; void add(int x,int y) { tot++; next[tot]=point[x]; point[x]=tot; v[tot]=y; tot++; next[tot]=point[y]; point[y]=tot; v[tot]=x; } void dfs(int x,int f) { size[x]=1; for (int i=point[x];i;i=next[i]) if (v[i]!=f) { deep[v[i]]=deep[x]+1; dfs(v[i],x); fa[v[i]]=x; size[x]+=size[v[i]]; if (size[v[i]]>size[son[x]]) son[x]=v[i]; } } void build(int k,int chain) { belong[k]=chain; pos[k]=++sz; l[k]=sz; r[k]=sz; if (!son[k]) return; build(son[k],chain); for (int i=point[k];i;i=next[i]) if (v[i]!=fa[k]&&v[i]!=son[k]) build(v[i],v[i]); r[k]=sz; } void pushdown(int now,int l,int r) { if (!delta[now]) return; delta[now<<1]+=delta[now]; delta[now<<1|1]+=delta[now]; int mid=(l+r)/2; tr[now<<1]+=(LL)(mid-l+1)*delta[now]; tr[now<<1|1]+=(LL)(r-mid)*delta[now]; delta[now]=0; } LL query(int now,int l,int r,int ll,int rr) { if (l>=ll&&r<=rr) return tr[now]; pushdown(now,l,r); int mid=(l+r)/2; LL ans=0; if (ll<=mid) ans+=query(now<<1,l,mid,ll,rr); if (rr>mid) ans+=query(now<<1|1,mid+1,r,ll,rr); return ans; } void change(int now,int l,int r,int ll,int rr,LL v) { if (l>=ll&&r<=rr){ tr[now]+=(LL)v*(r-l+1); delta[now]+=v; return; } pushdown(now,l,r); int mid=(l+r)/2; if (ll<=mid) change(now<<1,l,mid,ll,rr,v); if (rr>mid) change(now<<1|1,mid+1,r,ll,rr,v); tr[now]=tr[now<<1]+tr[now<<1|1]; } void solve(int x,int y,LL v) { while (belong[x]!=belong[y]) { if (deep[belong[x]]<deep[belong[y]]) swap(x,y); change(1,1,n,pos[belong[x]],pos[x],v); x=fa[belong[x]]; } if (deep[x]>deep[y]) swap(x,y); change(1,1,n,pos[x],pos[y],v); } int main() { freopen("a.in","r",stdin); scanf("%d",&n); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); x++; y++; add(x,y); } deep[1]=1; dfs(1,0); build(1,1); scanf("%d",&t); for (int i=1;i<=t;i++) { char s[10]; scanf("%s",s); if (s[0]=='A'){ int x,y; LL z; scanf("%d%d%I64d",&x,&y,&z); x++; y++; solve(x,y,z); } else{ int x; scanf("%d",&x); x++; printf("%I64d\n",query(1,1,n,l[x],r[x])); } } }
相关文章推荐
- datrie树修改
- 搞懂树状数组(转)
- unity 4 Please check your configuration file and verify this type name.
- 表视图实现好友分组(可收起放下)
- Linux进程通信共享内存函数
- C++ 无锁队列 ABA <2>
- bzoj3524 [Poi2014]Couriers
- Codeforces Round #350 (Div. 2) F. Restore a Number 模拟构造题
- iOS TextField监听、判断按钮可用及BUG修复
- spring @Transactional 方法内事务不起作用的解决办法
- 47905375
- Leetcode 20. Valid Parentheses
- 这或许是华为荣耀六root的另一种方法。
- reflow(回流)和repaint(重绘)及其优化
- iOS开发之基础视图— UISwitch
- Volley StringRequest和JSONObjectRequest使用几个细节
- hdu 2084 数塔
- saltstack之(九)配置管理源码部署Nginx
- HDU 2851.Lode Runner【DP动态规划】【5月11】
- POJ2234(二进制和平衡状态概念)