[點分樹(動態點分治)] 洛谷P6329 震波
阿新 • • 發佈:2020-12-08
Code
#include <bits/stdc++.h> using namespace std; #define RG register int #define LL long long template<typename elemType> inline void Read(elemType &T){ elemType X=0,w=0; char ch=0; while(!isdigit(ch)) {w|=ch=='-';ch=getchar();} while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); T=(w?-X:X); } const int maxn=100010; const int INF=1<<30; struct Graph{ struct edge{int Next,to;}; edge G[maxn<<1]; int head[maxn],cnt; Graph():cnt(2){} void clear(int n){cnt=2;fill(head,head+n+2,0);} void add_edge(int u,int v){ G[cnt].to=v; G[cnt].Next=head[u]; head[u]=cnt++; } }; template<size_t n> struct HLD{ int fa[n],top[n],hson[n],sz[n],deep[n]; Graph &G;int root; HLD(Graph &_G):G(_G){} void DFS_Init(int u){ sz[u]=1;deep[u]=deep[fa[u]]+1; for(int i=G.head[u];i;i=G.G[i].Next){ int v=G.G[i].to; if(v==fa[u]) continue; fa[v]=u; DFS_Init(v); sz[u]+=sz[v]; if(sz[hson[u]]<sz[v]) hson[u]=v; } } void DFS(int u,int anc){ top[u]=anc; if(!hson[u]) return; DFS(hson[u],anc); for(int i=G.head[u];i;i=G.G[i].Next){ int v=G.G[i].to; if(v==fa[u] || v==hson[u]) continue; DFS(v,v); } } void build(int _root){ root=_root; fa[root]=0;DFS_Init(root);DFS(root,root); } int LCA(int u,int v){ while(top[u]!=top[v]){ if(deep[top[u]]<deep[top[v]]) swap(u,v); u=fa[top[u]]; } if(deep[u]>deep[v]) swap(u,v); return u; } int getDis(int u,int v){return deep[u]+deep[v]-(deep[LCA(u,v)]<<1);} }; template<typename elemType> struct BIT{ inline int lowbit(int x){return x&(-x);} int n;vector<elemType> Node; void build(int _n){n=_n;Node.resize(n+1);} void Update(int x,elemType Add){ ++x;for(;x<=n;x+=lowbit(x)) Node[x]+=Add; } elemType PrefixSum(elemType x){ ++x;x=min(x,n);elemType Res=0; for(;x;x-=lowbit(x)) Res+=Node[x];return Res; } elemType Query(int L,int R){return PrefixSum(R)-PrefixSum(L-1);} }; Graph G; HLD<maxn> hld(G); BIT<int> TR1[maxn],TR2[maxn]; int Value[maxn],Size[maxn],Fa[maxn]; bool vis[maxn]; int N,M,Root,CurSize,MaxSize; void GetRoot(int u,int fa){ Size[u]=1; int mx=0; for(int i=G.head[u];i;i=G.G[i].Next){ int v=G.G[i].to; if(vis[v] || v==fa) continue; GetRoot(v,u); Size[u]+=Size[v]; mx=max(mx,Size[v]); } mx=max(mx,CurSize-Size[u]); if(mx<MaxSize){MaxSize=mx;Root=u;} } void Divide(int u,int fa){ vis[u]=true;Fa[u]=fa; TR1[u].build((CurSize>>1)+1); TR2[u].build(CurSize+1); for(int i=G.head[u];i;i=G.G[i].Next){ int v=G.G[i].to; if(vis[v]) continue; CurSize=MaxSize=Size[v]; Root=0;GetRoot(v,0); Divide(Root,u); } } void Change(int u,int v){ TR1[u].Update(0,v); for(int x=u;Fa[x];x=Fa[x]){ int d=hld.getDis(u,Fa[x]); TR1[Fa[x]].Update(d,v); TR2[x].Update(d,v); } } int Ask(int u,int K){ int ans=TR1[u].PrefixSum(K); for(int x=u;Fa[x];x=Fa[x]){ int d=hld.getDis(u,Fa[x]); if(d>K) continue; ans+=TR1[Fa[x]].PrefixSum(K-d); ans-=TR2[x].PrefixSum(K-d); } return ans; } int main(){ Read(N);Read(M); for(int i=1;i<=N;++i) Read(Value[i]); for(int i=1;i<=N-1;++i){ int u,v;Read(u);Read(v); G.add_edge(u,v); G.add_edge(v,u); } hld.build(1);CurSize=N; CurSize=MaxSize=N;Root=0;GetRoot(1,0); Divide(Root,0); for(int i=1;i<=N;++i) Change(i,Value[i]); int lastans=0; while(M--){ int opt,u,v; Read(opt);Read(u);Read(v); u^=lastans;v^=lastans; if(opt){Change(u,v-Value[u]);Value[u]=v;} else printf("%d\n",lastans=Ask(u,v)); } return 0; }