【BZOJ4034】树上操作(HAOI2015)-树链剖分
2017-08-10 17:35
441 查看
测试地址:树上操作
做法:其实是很明显的树链剖分了,单点修改+子树修改+路径询问,写这个是为了复健,因为感觉好久没写这种代码量大的题了,结果交上去一发直接过,美滋滋。
以下是本人代码:
做法:其实是很明显的树链剖分了,单点修改+子树修改+路径询问,写这个是为了复健,因为感觉好久没写这种代码量大的题了,结果交上去一发直接过,美滋滋。
以下是本人代码:
#include <cstdio> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define ll long long using namespace std; int n,m; int tot=0,first[100010]={0},in[100010]={0},out[100010]={0},tim=0; int dep[100010],siz[100010],son[100010],fa[100010],pos[100010],top[100010]; ll sum[400010],tag[400010],val[100010]; struct edge {int v,next;} e[200010]; void insert(int a,int b) { e[++tot].v=b; e[tot].next=first[a]; first[a]=tot; } void dfs1(int v) { siz[v]=1;son[v]=0; for(int i=first[v];i;i=e[i].next) if (e[i].v!=fa[v]) { fa[e[i].v]=v; dep[e[i].v]=dep[v]+1; dfs1(e[i].v); if (siz[son[v]]<siz[e[i].v]) son[v]=e[i].v; siz[v]+=siz[e[i].v]; } } void dfs2(int v,int p) { top[v]=p; pos[++tim]=v; in[v]=tim; if (son[v]) dfs2(son[v],p); for(int i=first[v];i;i=e[i].next) if (e[i].v!=fa[v]&&e[i].v!=son[v]) dfs2(e[i].v,e[i].v); out[v]=tim; } void pushdown(int no,int l,int r) { if (tag[no]!=0) { int mid=(l+r)>>1; tag[no<<1]+=tag[no]; tag[no<<1|1]+=tag[no]; sum[no<<1]+=((ll)(mid-l+1))*tag[no]; sum[no<<1|1]+=((ll)(r-mid))*tag[no]; tag[no]=0; } } void pushup(int no) { sum[no]=sum[no<<1]+sum[no<<1|1]; } void buildtree(int no,int l,int r) { if (l==r) { sum[no]=val[pos[l]]; return; } int mid=(l+r)>>1; buildtree(no<<1,l,mid); buildtree(no<<1|1,mid+1,r); pushup(no); } void add(int no,int l,int r,int s,int t,ll val) { if (l>=s&&r<=t) { tag[no]+=val; sum[no]+=((ll)(r-l+1))*val; return; } int mid=(l+r)>>1; pushdown(no,l,r); if (s<=mid) add(no<<1,l,mid,s,t,val); if (t>mid) add(no<<1|1,mid+1,r,s,t,val); pushup(no); } ll segquery(int no,int l,int r,int s,int t) { if (l>=s&&r<=t) { return sum[no]; } int mid=(l+r)>>1; ll ss=0; pushdown(no,l,r); if (s<=mid) ss+=segquery(no<<1,l,mid,s,t); if (t>mid) ss+=segquery(no<<1|1,mid+1,r,s,t); pushup(no); return ss; } ll query(int x,int y) { ll ans=0; while(top[x]!=top[y]) { if (dep[top[x]]<dep[top[y]]) swap(x,y); ans+=segquery(1,1,n,in[top[x]],in[x]); x=fa[top[x]]; } if (dep[x]<dep[y]) swap(x,y); ans+=segquery(1,1,n,in[y],in[x]); return ans; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&val[i]); for(int i=1;i<n;i++) { int a,b; scanf("%d%d",&a,&b); insert(a,b);insert(b,a); } fa[1]=siz[0]=0; dep[1]=1; dfs1(1); dfs2(1,1); buildtree(1,1,n); for(int i=1;i<=m;i++) { int op,a; ll d; scanf("%d",&op); if (op==1) { scanf("%d%lld",&a,&d); add(1,1,n,in[a],in[a],d); } if (op==2) { scanf("%d%lld",&a,&d); add(1,1,n,in[a],out[a],d); } if (op==3) { scanf("%d",&a); printf("%lld\n",query(1,a)); } } return 0; }
相关文章推荐
- |BZOJ 4034|树链剖分|线段树|[HAOI2015]树上操作
- 【树链剖分(DFS序)+线段树】BZOJ4034(HAOI2015)[树上操作]题解
- bzoj 4034: [HAOI2015]树上操作 (树链剖分)
- bzoj4034 [HAOI2015]树上操作(树链剖分)
- BZOJ 4034: [HAOI2015]树上操作【树链剖分】【DFS序】
- 【BZOJ4034】【HAOI2015】树上操作(树链剖分)
- [树链剖分]bzoj 4034—— [HAOI2015]树上操作
- 【BZOJ 4034】【HAOI 2015】树上操作【树链剖分】
- bzoj 4034: [HAOI2015]树上操作 树链剖分
- [BZOJ 4034][HAOI 2015] 树上操作 树链剖分+DFS序
- BZOJ[4034][HAOI2015]树上操作 树链剖分+线段树
- bzoj 4034: [HAOI2015]树上操作(树链剖分+线段树区间更新)
- BZOJ 4034 [HAOI2015]树上操作 树链剖分
- 【bzoj4034】【HAOI2015】【树上操作】【树链剖分】
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- BZOJ 4034 :[HAOI2015]树上操作 树链剖分裸题
- bzoj 4034: [HAOI2015]树上操作——树链剖分
- 【树链剖分】bzoj4034: [HAOI2015]树上操作
- BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )
- BZOJ-4034: [HAOI2015]树上操作 (树链剖分 入门题 子树整体修改 线段树 区间修改+查询)