4034: [HAOI2015]T2 (树链剖分)
来源:互联网 发布:openwrt端口转发 编辑:程序博客网 时间:2024/04/30 13:03
树链剖分+线段树区间更新和区间求和。
注意,一个子树的所有点上的序号在线段树上的位置是连续的,意识到这点这个题就是模版题了。
另外关于树链剖分的细节,第二次递归的时候要先计算重边对应结点否则会出错。
线段树中,push_down的部分注意可能溢出int。最终答案要用longlong。
#include<iostream>#include<cstdio>#include<cstring>#include<vector>#include<cmath>#include<map>#include<string>#include<set>#include<queue>#include<algorithm>using namespace std;typedef long long LL;const int maxn=100010;int n;int arr[maxn];LL sum[4*maxn],tar[4*maxn];int head[maxn],to[maxn*2],nxt[maxn*2],edge;int siz[maxn],son[maxn],fa[maxn],top[maxn],dep[maxn],id[maxn],rid[maxn],tot;int eid[maxn];void init(){ tot=0; memset(son,-1,sizeof(son)); edge=0; memset(head,-1,sizeof(head));}void addEdge(int u,int v){ to[edge]=v,nxt[edge]=head[u],head[u]=edge++; to[edge]=u,nxt[edge]=head[v],head[v]=edge++;}void dfs1(int now,int f,int d){ siz[now]=1; dep[now]=d; fa[now]=f; for(int i=head[now]; i!=-1; i=nxt[i]) { int v=to[i]; if(v!=f) { dfs1(v,now,d+1); if(son[now]==-1||siz[son[now]]<siz[v]) son[now]=v; siz[now]+=siz[v]; } }}void dfs2(int now,int tp){ id[now]=++tot; rid[id[now]]=now; top[now]=tp; if(son[now]!=-1) dfs2(son[now],tp); for(int i=head[now]; i!=-1; i=nxt[i]) { int v=to[i]; if(v!=fa[now]&&v!=son[now]) { dfs2(v,v); } } eid[now]=tot;}void push_up(int o){ sum[o]=sum[o<<1]+sum[o<<1|1];}void push_down(int o,int m){ if(tar[o]) { tar[o<<1]+=tar[o]; tar[o<<1|1]+=tar[o]; sum[o<<1]+=tar[o]*(m-m/2); sum[o<<1|1]+=tar[o]*(m/2); tar[o]=0; }}void Add(int o,int l,int r,LL val,int ql,int qr){ if(ql<=l&&r<=qr) { sum[o]+=(r-l+1)*val; tar[o]+=val; } else { push_down(o,r-l+1); int m=l+(r-l)/2; if(ql<=m) Add(o<<1,l,m,val,ql,qr); if(m<qr) Add(o<<1|1,m+1,r,val,ql,qr); push_up(o); }}LL querySum(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr) return sum[o]; else { push_down(o,r-l+1); int m=l+(r-l)/2; LL s=0; if(ql<=m) s+=querySum(o<<1,l,m,ql,qr); if(m<qr) s+=querySum(o<<1|1,m+1,r,ql,qr); return s; }}void build(int o,int l,int r){ tar[o]=0; if(l==r) { sum[o]=arr[rid[l]]; } else { int m=l+(r-l)/2; build(o<<1,l,m); build(o<<1|1,m+1,r); push_up(o); }}LL getSum(int x,int y){ LL s=0; while(top[x]!=top[y]) { if(dep[top[x]]>dep[top[y]]) swap(x,y); s+=querySum(1,1,n,id[top[y]],id[y]); y=fa[top[y]]; } if(dep[x]>dep[y]) swap(x,y); s+=querySum(1,1,n,id[x],id[y]); return s;}int main(){ int m; scanf("%d%d",&n,&m); init(); for(int i=1; i<=n; ++i) scanf("%d",&arr[i]); for(int i=1; i<n; ++i) { int a,b; scanf("%d%d",&a,&b); addEdge(a,b); } dfs1(1,-1,1); dfs2(1,1); build(1,1,n); while(m--) { int x,a,b; scanf("%d",&x); if(x==1) { scanf("%d%d",&a,&b); Add(1,1,n,b,id[a],id[a]); } else if(x==2) { scanf("%d%d",&a,&b); Add(1,1,n,b,id[a],eid[a]); } else if(x==3) { scanf("%d",&a); printf("%lld\n",getSum(1,a)); } } return 0;}
0 0
- 4034: [HAOI2015]T2 (树链剖分)
- BZOJ 4034 [HAOI2015]T2 树链剖分
- [BZOJ 4034][HAOI2015]T2 [树链剖分]
- BZOJ 4034 [HAOI2015]T2 树链剖分+线段树
- bzoj 4034 [HAOI2015]T2 树链剖分+线段树
- 4034: [HAOI2015]T2 树链剖分+线段树
- BZOJ 4034: [HAOI2015]T2|线段树|树链剖分
- BZOJ-4034- [HAOI2015]T2-树链剖分+线段树
- bzoj 4034: [HAOI2015]T2
- BZOJ 4034: [HAOI2015]T2
- BZOJ 4034 [HAOI2015]T2
- bzoj 4034 [HAOI2015]T2
- 4034: [HAOI2015]T2
- bzoj4034[HAOI2015]T2 - 树链剖分
- Bzoj4034:[HAOI2015]T2:树链剖分
- [BZOJ4034] [HAOI2015] T2 - 树链剖分
- bzoj4034 HAOI2015 T2 树链剖分
- 树链剖分模板题 [HAOI2015]T2
- 基于AppDomain的"插件式"开发
- java HashMap
- 从svn中check out maven项目 所遇到的一系列问题:
- IgnoreCaseSort
- POJ 2688 简单的TSP问题,状压DP
- 4034: [HAOI2015]T2 (树链剖分)
- my.ini配置文件引起的"无法启动mysql服务,发生错误1067"
- .bash_profile和.bashrc的区别(如何设置生效)
- Android进阶之大话设计模式
- struts 2的OGNL表达式
- 升级到OSX10.11后cocopods不正常的问题
- springmvc之json格式配置
- listView 设置setSection无效
- Android和iOS中Cocos2D日志为什么会出现skip frames