bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树
Posted guangheli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树相关的知识,希望对你有一定的参考价值。
Code:
#include<bits/stdc++.h> #define setIO(s) freopen(s".in","r",stdin) #define maxn 6011111 #define N 500010 #define inf 0x7f7f7f using namespace std; int hd[N],nx[N],to[N],cnt; int n,m,val[N],vis[N]; void add(int u,int v) { nx[++cnt]=hd[u],hd[u]=cnt,to[cnt]=v; } namespace heavyedge{ int dep[N],hson[N],fa[N],siz[N],top[N]; void dfs1(int u,int ff) { dep[u]=dep[ff]+1,fa[u]=ff,siz[u]=1; for(int i=hd[u];i;i=nx[i]) if(to[i]!=ff) { dfs1(to[i],u),siz[u]+=siz[to[i]]; if(siz[to[i]]>siz[hson[u]]) hson[u]=to[i]; } } void dfs2(int u,int tp) { top[u]=tp; if(hson[u]) dfs2(hson[u],tp); for(int i=hd[u];i;i=nx[i]) { if(to[i]==fa[u]||to[i]==hson[u]) continue; dfs2(to[i],to[i]); } } int LCA(int u,int v) { while(top[u]!=top[v]) dep[top[u]] < dep[top[v]] ? v = fa[top[v]] : u = fa[top[u]]; return dep[u] < dep[v] ? u : v; } int main() { dfs1(1,0), dfs2(1,1); return 0; } }; int Dis(int u,int v) { return heavyedge::dep[u] + heavyedge::dep[v] - (heavyedge::dep[heavyedge::LCA(u,v)] << 1); } int siz[N],f[N],root,sn,Fa[N]; int GetRoot(int u,int ff) { siz[u] = 1,f[u] = 0; for(int i = hd[u]; i ; i = nx[i]) { if(to[i] == ff || vis[to[i]]) continue; GetRoot(to[i],u); siz[u] += siz[to[i]]; f[u] = max(f[u],siz[to[i]]); } f[u] = max(f[u],sn - siz[u]); if(f[u] < f[root]) root = u; } void dfs(int u) { vis[u] = 1; for(int i = hd[u]; i ; i = nx[i]) { if(vis[to[i]]) continue; root = 0, sn = siz[to[i]], GetRoot(to[i],u); Fa[root] = u, dfs(root); } } struct Segment_Tree{ #define ls (t[o].l) #define rs (t[o].r) int tot; struct Node { int l,r,v; }t[maxn<<1]; void update(int &o,int l,int r,int p,int w) { if(!o) o = ++cnt; t[o].v += w; if(l == r) return; int mid = (l + r) >> 1; if(p <= mid) update(t[o].l,l,mid,p,w); else update(t[o].r,mid + 1,r,p,w); } int query(int o,int l,int r,int L,int R) { if(!o || l > r) return 0; if(l >= L && r <= R) return t[o].v; int mid = (l + r) >> 1,res = 0; if(L <= mid) res += query(t[o].l,l,mid,L,R); if(R >= mid + 1) res += query(t[o].r,mid + 1,r, L,R); return res; } }T; int ans = 0,rt[N]; #define fax(x) (x + n) void Update(int x,int k,int w) { T.update(rt[x],0,n,0,w),T.update(rt[x],0,n,k + 1,-w); for(int i = x; Fa[i]; i = Fa[i]) { int dis = Dis(x, Fa[i]); if(k - dis < 0) continue; T.update(rt[Fa[i]],0,n,0,w),T.update(rt[Fa[i]],0,n,k - dis + 1,-w); T.update(rt[fax(i)],0,n,0,w),T.update(rt[fax(i)],0,n,k - dis + 1,-w); } } int Query(int x) { int res = T.query(rt[x],0,n,0,0); for(int i = x; Fa[i] ; i = Fa[i]) { int dis = Dis(x, Fa[i]); res += T.query(rt[Fa[i]],0,n,0,dis); res -= T.query(rt[fax(i)],0,n,0,dis); } return res; } char str[20]; int main() { // setIO("input"); scanf("%d%d",&n,&m); for(int i = 1,u,v;i < n; ++i) scanf("%d%d",&u,&v), add(u,v),add(v,u); heavyedge :: main(); f[0] = inf, sn = n,root = 0,GetRoot(1,0), dfs(root); while(m--) { int x,y,z; scanf("%s",str); if(str[0] == ‘M‘) scanf("%d%d%d",&x,&y,&z),Update(x,y,z); if(str[0] == ‘Q‘) scanf("%d",&x), printf("%d\n",Query(x)); } return 0; }
以上是关于bzoj 4372: 烁烁的游戏 动态点分治_树链剖分_线段树的主要内容,如果未能解决你的问题,请参考以下文章