树链剖分+线段树 HDU3966 权值在点 模板
来源:互联网 发布:程序员改bug 编辑:程序博客网 时间:2024/06/06 02:07
树链剖分模板题。
#include<stdio.h>#include<string.h>#include<stdlib.h>#include<vector>#include<algorithm>#include<iostream>using namespace std;#define maxn 50010int n,m,Q;int tim;//时间戳int a[maxn];//树上每个节点的初始值int siz[maxn];//siz[u]表示以u为根的子树的节点数int top[maxn];//树链上深度最小的点int son[maxn];//重儿子int dep[maxn];//深度int tid[maxn];//节点的时间戳int tid1[maxn];//tid[i]=j表示时间戳为i的节点是jint fa[maxn];//父节点bool vis[maxn];vector<int>edge[maxn];void init(int n){ for(int i=1;i<=n;i++) { siz[i]=top[i]=son[i]=0; dep[i]=tid[i]=tid1[i]=fa[i]=0; vis[i]=false; tim=0; edge[i].clear(); }}void add(int x,int y) //无向图加双向边{ edge[x].push_back(y); edge[y].push_back(x);}//树链剖分void dfs1(int u,int pre){ vis[u]=true; siz[u]=1; fa[u]=pre; dep[u]=dep[pre]+1;//注意根节点比较特殊 int l=edge[u].size(); for(int i=0;i<l;i++) { int v=edge[u][i]; if(v!=fa[u]&&vis[v]==false) { dfs1(v,u); siz[u]+=siz[v]; if(son[u]==0) son[u]=v; else if(siz[son[u]]<siz[v]) son[u]=v; } }}void dfs2(int u,int tp)//tp表示节点u的顶部;{ vis[u]=true; tid[u]=++tim; tid1[tim]=u; top[u]=tp; if(son[u]!=0) { dfs2(son[u],tp);//同一条重链的顶部相同 } int l=edge[u].size(); for(int i=0;i<l;i++) { int v=edge[u][i]; if(v!=fa[u]&&v!=son[u]&&vis[v]==false)//注意去掉重儿子 { dfs2(v,v); } }}void update(int i,int l,int r,int v);//线段树更新函数void change(int x,int y,int val){ while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); update(1,tid[top[x]],tid[x],val);//dfs2时顶部先访问,故tid[top]较小 x=fa[top[x]];//因为top[x]->x路径上的所有点已经被更新了 } if(dep[x]>dep[y])//同一条重链上深度小的tid小 swap(x,y); update(1,tid[x],tid[y],val);}//线段树部分struct node{ int l,r,val,lazy;}q[maxn*4];void build(int i,int l,int r){ q[i].l=l; q[i].r=r; q[i].lazy=q[i].val=0; if(l==r) { q[i].val=a[tid1[l]]; return; } int mid=(l+r)/2; build(i*2,l,mid); build(i*2+1,mid+1,r);}void pushdown(int i){ if(q[i].lazy!=0) { q[i*2].val+=q[i].lazy; q[i*2+1].val+=q[i].lazy; q[i*2].lazy+=q[i].lazy; q[i*2+1].lazy+=q[i].lazy; q[i].lazy=0; }}void update(int i,int l,int r,int v){ if(q[i].l==l&&q[i].r==r) { q[i].val+=v; q[i].lazy+=v; return; } pushdown(i); int mid=(q[i].l+q[i].r)/2; if(r<=mid) update(i*2,l,r,v); else if(l>mid) update(i*2+1,l,r,v); else { update(i*2,l,mid,v); update(i*2+1,mid+1,r,v); }}int query(int i,int x){ if(q[i].l==x&&q[i].r==x) { return q[i].val; } pushdown(i); int mid=(q[i].l+q[i].r)/2; if(x<=mid) return query(i*2,x); else return query(i*2+1,x);}int main(void){ int i,j,k,x,y,z; char op[2]; while(scanf("%d%d%d",&n,&m,&Q)!=EOF) { init(n); for(i=1;i<=n;i++) scanf("%d",&a[i]); for(i=1;i<=m;i++) { scanf("%d%d",&x,&y); add(x,y); } dfs1(1,0); memset(vis,false,sizeof(vis)); dfs2(1,1); build(1,1,n); while(Q--) { scanf("%s",op); if(op[0]=='Q') { scanf("%d",&x); printf("%d\n",query(1,tid[x])); } else { scanf("%d%d%d",&x,&y,&z); if(op[0]=='I') change(x,y,z); else change(x,y,-z); } } } return 0;}
阅读全文
0 0
- 树链剖分+线段树 HDU3966 权值在点 模板
- hdu3966 点权模板-树链部分
- 树链剖分+点权+hdu3966
- 树链剖分+线段树 hdu3966 Aragorn's Story
- hdu3966 Aragorn's Story【树链剖分+线段树】
- 【HDU3966】Aragorn's Story(树链剖分+线段树)
- HDU3966(树链剖分) 模板题
- 【HDU3966】Aragorn's Story-树链剖分+线段树区间维护
- HDU3966 Aragorn's Story(树链剖分+线段树)
- hdu3966 树链剖分(入门,点)
- hdu3966 Aragorn's Story(基于点权的树链剖分模板题(模板是基于已完善的边权树剖模板修改的,模板较较完善))
- HDU3966(树链剖分(点权)入门)链分治
- 树链剖分+线段树 POJ3237 权值在边 模板
- hdu3966(数链剖分+线段树区间更新)
- HDU3966-树链剖分(区间更新,点查询)
- 树链剖分(线段树区间更新求和(lazy操作)hdu3966)
- HDU3966(树链剖分)
- hdu3966 树链剖分
- uva11175
- The Stack Is An Implementation Detail, Part One
- 小型超市网上购物系统开发项目总结
- #{}和${}的区别
- PAT 甲级 1106. Lowest Price in Supply Chain (25)
- 树链剖分+线段树 HDU3966 权值在点 模板
- ios开发 Could not signal service com.apple.WebKit.WebContent: 113
- eclipse快捷键整理
- 单例模式
- ionic cordova andoid环境配置
- 运算符重载 编程题#2(Coursera 程序设计与算法 专项课程3 C++程序设计;重载:& operator-)
- PHP实现HTTP断点续传的方法
- 密码输入框显示为文字
- poj 2828 Buy Tickets