1. 程式人生 > >【BZOJ3730】震波(動態點分治)

【BZOJ3730】震波(動態點分治)

www pre size getch post str http clu cto

【BZOJ3730】震波(動態點分治)

題面

BZOJ
題意
給定一棵樹,
每次詢問到一個點的距離\(<=K\)的點的權值之和
動態修改權值,
強制在線

題解

正常的\(DP\)???
很簡單呀。
每次暴力往父親跳,不斷的加值,
然後容斥一下就行了

現在要動態維護
就維護一下動態點分治

但是現在記錄起來沒那麽容易了
於是開兩棵線段樹
每次做一下差
不斷暴跳點分樹的父親就行啦

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm> #include<set> #include<map> #include<vector> #include<queue> using namespace std; #define MAX 120000 inline int read() { int x=0,t=1;char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-')ch=getchar(); if(ch=='-'
)t=-1,ch=getchar(); while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar(); return x*t; } struct Line{int v,next,w,rt;}e[MAX<<1],E[MAX<<1]; int h[MAX],cnt=1; inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w,0};h[u]=cnt++;} /************************************************************************/
int dfn[MAX],top[MAX],dep[MAX],ssize[MAX],hson[MAX],fa[MAX]; int dis[MAX]; void dfs1(int u,int ff) { fa[u]=ff;ssize[u]=1;dep[u]=dep[ff]+1; for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(v==ff)continue; dis[v]=dis[u]+e[i].w; dfs1(v,u); ssize[u]+=ssize[v]; if(ssize[hson[u]]<ssize[v])hson[u]=v; } } void dfs2(int u,int tp) { top[u]=tp; if(hson[u])dfs2(hson[u],tp); for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(v==fa[u]||v==hson[u])continue; dfs2(v,v); } } int LCA(int u,int v) { while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]])swap(u,v); u=fa[top[u]]; } return dep[u]<dep[v]?u:v; } int Dis(int u,int v) { return dis[u]+dis[v]-dis[LCA(u,v)]*2; } /************************************************************************/ int sum[MAX],size[MAX],Fa[MAX]; int n,Q,m,val[MAX]; int Size,root,minr; bool vis[MAX]; void Getroot(int u,int ff) { size[u]=1; int ret=0; for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(v==ff||vis[v])continue; Getroot(v,u); size[u]+=size[v]; ret=max(ret,size[v]); } ret=max(ret,Size-size[u]); if(ret<minr)minr=ret,root=u; } void DFS(int u,int ff) { vis[u]=true;Fa[u]=ff; for(int i=h[u];i;i=e[i].next) { int v=e[i].v; if(vis[v])continue; minr=n;Size=size[v]; Getroot(v,u); DFS(root,u); } } struct Node { int ls,rs; int v; }t[MAX*150]; int tot,rt[MAX<<1]; void Modify(int &now,int l,int r,int pos,int w) { if(!now)now=++tot;t[now].v+=w; if(l==r)return; int mid=(l+r)>>1; if(pos<=mid)Modify(t[now].ls,l,mid,pos,w); else Modify(t[now].rs,mid+1,r,pos,w); } int Query(int now,int l,int r,int L,int R) { if(!now)return 0; if(L<=l&&r<=R)return t[now].v; int ret=0,mid=(l+r)>>1; if(L<=mid)ret+=Query(t[now].ls,l,mid,L,R); if(R>mid)ret+=Query(t[now].rs,mid+1,r,L,R); return ret; } void PModify(int u,int w) { Modify(rt[u],0,n,0,w); for(int i=u;Fa[i];i=Fa[i]) { int dist=Dis(u,Fa[i]); Modify(rt[Fa[i]],0,n,dist,w); Modify(rt[i+n],0,n,dist,w); } } int PQuery(int u,int K) { int ret=Query(rt[u],0,n,0,K); for(int i=u;Fa[i];i=Fa[i]) { int dist=Dis(u,Fa[i]); if(dist>K)continue; ret+=Query(rt[Fa[i]],0,n,0,K-dist); ret-=Query(rt[i+n],0,n,0,K-dist); } return ret; } int main() { n=read();Q=read(); for(int i=1;i<=n;++i)val[i]=read(); for(int i=1,u,v;i<n;++i)u=read(),v=read(),Add(u,v,1),Add(v,u,1); dfs1(1,0);dfs2(1,1); minr=Size=n;Getroot(1,0); DFS(root,0); for(int i=1;i<=n;++i)PModify(i,val[i]); int ans=0; while(Q--) { int opt=read(); if(opt) { int u=read()^ans,v=read()^ans; PModify(u,v-val[u]); val[u]=v; } else { int u=read()^ans,K=read()^ans; ans=PQuery(u,K); printf("%d\n",ans); } } return 0; }

【BZOJ3730】震波(動態點分治)