hdu 3966 树链剖分 模板题
来源:互联网 发布:邵氏孤儿 知乎 编辑:程序博客网 时间:2024/06/06 12:20
题意:给一棵树,并给定各个点权的值,然后有3种操作:
I C1 C2 K: 把C1与C2的路径上的所有点权值加上K
D C1 C2 K:把C1与C2的路径上的所有点权值减去K
Q C:查询节点编号为C的权值
分析:典型的树链剖分题目,先进行剖分,然后用线段树去维护即可,注意HDU的OJ采用Windows系统,容易爆栈,所以在代码
前面加上:#pragma comment(linker, “/STACK:1024000000,1024000000”)进行手动扩栈。
下面有代码和注释
纯模板:
#pragma comment(linker,"/STACK:1024000000,1024000000")#include <iostream>#include <cstring>#include <algorithm>#include <cstdio>#include <vector>using namespace std;const int N=50010;int n,m,Q;int tim;int num[N],siz[N],top[N],son[N];int dep[N],tid[N],ran[N],fa[N];int head[N],to[2*N],nex[2*N],edge;void init(){ memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); tim=0; edge=0;}void addedge(int u,int v){ to[edge]=v,nex[edge]=head[u],head[u]=edge++; to[edge]=u,nex[edge]=head[v],head[v]=edge++;}void dfs1(int u,int father,int d){ dep[u]=d; fa[u]=father; siz[u]=1; for(int i=head[u];~i;i=nex[i]) { int v=to[i]; if(v!=father) { dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } }}void dfs2(int u,int tp){ top[u]=tp; tid[u]=++tim; ran[tid[u]]=u; if(son[u]==-1) return ; dfs2(son[u],tp); for(int i=head[u];~i;i=nex[i]) { int v=to[i]; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); }}#define lson l,mid,rt<<1#define rson mid+1,r,rt<<1|1int sum[4*N],col[4*N];void PushUP(int rt){ sum[rt]=max(sum[rt<<1],sum[rt<<1]|1);}void PushDown(int rt,int m){ if(col[rt]) { col[rt<<1]+=col[rt]; col[rt<<1|1]+=col[rt]; sum[rt<<1]+=(m-(m>>1))*col[rt]; sum[rt<<1|1]+=(m>>1)*col[rt]; col[rt]=0; }}void Build(int l,int r,int rt){ col[rt]=0; if(l==r) { sum[rt]=num[ran[l]]; return ; } int mid=(l+r)>>1; Build(lson); Build(rson); PushUP(rt); }void Update(int L,int R,int v,int l,int r,int rt){ if(L<=l&&R>=r) { col[rt]+=v; sum[rt]+=v*(r-l+1); return ; } PushDown(rt,r-l+1); int mid=(l+r)>>1; if(L<=mid) { Update(L,R,v,lson); } if(R>mid) Update(L,R,v,rson); PushUP(rt);}int Query(int l,int r,int rt,int val){ if(l==r) { return sum[rt]; } PushDown(rt,r-l+1); int mid=(l+r)>>1; int ret=0; if(val<=mid) ret=Query(lson,val); else ret=Query(rson,val); PushUP(rt); return ret;}void Change(int x,int y,int val){ while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); Update(tid[top[x]],tid[x],val,1,n,1); x=fa[top[x]]; } if(dep[x]>dep[y]) swap(x,y); Update(tid[x],tid[y],val,1,n,1);}int main(){ char oper[5]; int a,b,c; while(~scanf("%d%d%d",&n,&m,&Q)) { init(); for(int i=1;i<=n;i++) scanf("%d",&num[i]); for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); addedge(a,b); } dfs1(1,0,0); dfs2(1,1); Build(1,n,1); while(Q--){ scanf("%s",oper); if(oper[0]=='Q') { scanf("%d",&a); printf("%d\n",Query(1,n,1,tid[a]) ); } else { scanf("%d%d%d",&a,&b,&c); if(oper[0]=='D') c=-c; Change(a,b,c); } } }}
代码加注释:
void dfs1(int u,int father,int d) { dep[u]=d; fa[u]=father; siz[u]=1; for(int i=head[u];~i;i=next[i]) { int v=to[i]; if(v!=father) { dfs1(v,u,d+1); siz[u]+=siz[v]; if(son[u]==-1||siz[v]>siz[son[u]]) son[u]=v; } } }
阅读全文
0 0
- hdu 3966 树链剖分 模板题
- HDU 3966 树链剖分模板
- Hdu 3966 Aragorn's Story【树链剖分模板题】模板记录
- HDU 3966 Aragorn's Story 树链剖分模板
- HDU 3966 (树链剖分对点权值,模板)
- hdu 5458 树链剖分模板
- HDU 2966 模板题
- HDU 3722 KM模板题
- hdu 2222 DFA 模板题
- hdu 2586 lca模板题
- hdu 2203 kmp 模板题
- hdu 1711 KMP模板题
- hdu 1312 BFS模板题
- HDU 2544 dijkstra模板题
- HDU 3068 Manacher 模板题
- hdu 1711 kmp模板题
- 树链剖分 模板+HDU 3966 + SPOJ 375 【树剖入门】
- HDU 2844 Coins[【经典题】【模板题】
- 树链剖分 原理
- Linux下网络编程(1)——最简单TCP server/client例子
- 树链剖分 详解 比较好
- 算法作业HW13:Leetcode96 Unique Binary Search Trees
- 第一天
- hdu 3966 树链剖分 模板题
- MarkDown 图片大小问题
- Greedy walking spoj-ucv2013E (乘法逆元,数论基础)
- Vue通过ref父子组件拿值
- 做一个简单的射靶游戏
- Codeforces Round #415 (Div. 2) C. Do you want a date? 数学
- 大叔的高效团队定义,非常赞
- 详解coredump
- 思考一