【BZOJ3730】震波(動(dòng)態(tài)點(diǎn)分治)
題面
BZOJ
題意
給定一棵樹(shù),
每次詢問(wèn)到一個(gè)點(diǎn)的距離\(<=K\)的點(diǎn)的權(quán)值之和
動(dòng)態(tài)修改權(quán)值,
強(qiáng)制在線
題解
正常的\(DP\)???
很簡(jiǎn)單呀。
每次暴力往父親跳,不斷的加值,
然后容斥一下就行了
現(xiàn)在要?jiǎng)討B(tài)維護(hù)
就維護(hù)一下動(dòng)態(tài)點(diǎn)分治
但是現(xiàn)在記錄起來(lái)沒(méi)那么容易了
于是開(kāi)兩棵線段樹(shù)
每次做一下差
不斷暴跳點(diǎn)分樹(shù)的父親就行啦
#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;
}
轉(zhuǎn)載于:https://www.cnblogs.com/cjyyb/p/8279311.html
總結(jié)
以上是生活随笔為你收集整理的【BZOJ3730】震波(动态点分治)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。