点分治
点分治
询问树上距离为 k 的点对是否存在。

#include<bits/stdc++.h> using namespace std; const int MAX=20010; const int inf=1.5e8; int n,m,x,y,z,q[MAX],rt,siz[MAX],maxx[MAX],dis[MAX]; vector<pair<int,int> >g[MAX]; stack<int>tag; bool tf[inf],ret[MAX],vis[MAX]; int sum,d[MAX],cnt; inline int read(){ int x=0;char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c<='9'&&c>='0'){x=(x<<3)+(x<<1)+(c^48);c=getchar();} return x; } void zx(int,int); void csiz(int,int); void cdis(int,int); void dfs(int,int); int main(){ n=read();m=read(); for(int i=1;i<n;++i){ x=read();y=read();z=read(); g[x].push_back(make_pair(y,z)); g[y].push_back(make_pair(x,z)); }for(int i=1;i<=m;++i) q[i]=read(); maxx[rt=0]=MAX;sum=n;tf[0]=1;tag.push(0); zx(1,-1);csiz(rt,-1);dfs(rt,-1); for(int i=1;i<=m;++i) if(ret[i]) printf("AYE\n"); else printf("NAY\n"); } void zx(int u,int fa){ siz[u]=1;maxx[u]=0; for(int i=0;i<g[u].size();++i){ int v=g[u][i].first; if(v!=fa&&!vis[v]){ zx(v,u);siz[u]+=siz[v]; maxx[u]=max(maxx[u],siz[v]); } }maxx[u]=max(maxx[u],sum-maxx[u]); if(maxx[u]<maxx[rt]) rt=u; }void csiz(int u,int fa){ siz[u]=1; for(int i=0;i<g[u].size();++i){ int v=g[u][i].first; if(v!=fa&&!vis[v]){ csiz(v,u);siz[u]+=siz[v]; } } }void cdis(int u,int fa){ d[++cnt]=dis[u]; for(int i=0;i<g[u].size();++i){ int v=g[u][i].first; if(v!=fa&&!vis[v]){ dis[v]=dis[u]+g[u][i].second;cdis(v,u); } } } void dfs(int u,int fa){ vis[u]=1; for(int i=0;i<g[u].size();++i){ int v=g[u][i].first; if(v!=fa&&!vis[v]){ dis[v]=g[u][i].second; cnt=0;cdis(v,u); for(int j=1;j<=cnt;++j) for(int k=1;k<=m;++k) if(q[k]>=d[j]) ret[k]|=tf[q[k]-d[j]]; for(int j=1;j<=cnt;++j) tag.push(d[j]),tf[d[j]]=1; } }while(tag.top()) tf[tag.top()]=0,tag.pop(); for(int i=0;i<g[u].size();++i){ int v=g[u][i].first; if(v!=fa&&!vis[v]){ maxx[rt=0]=MAX;sum=siz[v]; zx(v,u);csiz(rt,-1);dfs(rt,-1); } } }
点分树

#include<bits/stdc++.h> using namespace std; const int MAX=1e5+10; int n,m,val[MAX],maxx,rt,siz[MAX],dep[MAX],fa[MAX],sum; int vis[MAX]; int in[MAX],chuo,ol[MAX<<1][22]; vector<int>g[MAX],c[2][MAX]; int opt,x,y,ans; inline int read(){ int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c<='9'&&c>='0'){x=(x<<3)+(x<<1)+(c^48);c=getchar();} return x*f; }void dfs(int,int,int); inline void init(); inline int qu(int,int); void zx(int,int); void csiz(int,int); void dfs1(int); inline int lowbit(int x){return x&-x;} inline void add(int op,int u,int x,int v){ x++; while(x<=siz[u]+op) c[op][u][x]+=v,x+=lowbit(x);//+op }inline int query(int op,int u,int x){ x=min(x+1,siz[u]+op);int ans=0; while(x) ans+=c[op][u][x],x-=lowbit(x); return ans; }inline void upda(int u,int v){ for(int i=u;i;i=fa[i]) add(0,i,qu(u,i),v); for(int i=u;fa[i];i=fa[i]) add(1,i,qu(u,fa[i]),v); } int main(){ //freopen("1.txt","r",stdin); n=read();m=read(); for(int i=1;i<=n;++i) val[i]=read(); for(int i=1;i<n;++i){ x=read();y=read(); g[x].push_back(y);g[y].push_back(x); }dfs(1,0,0);init();maxx=sum=n; zx(1,-1);csiz(rt,-1);dfs1(rt); for(int i=1;i<=n;++i) upda(i,val[i]); while(m--){ opt=read();x=read()^ans;y=read()^ans; if(opt==0){ ans=query(0,x,y); for(int i=x;fa[i];i=fa[i]){ int dis=qu(x,fa[i]); if(y>=dis) ans+=query(0,fa[i],y-dis)-query(1,i,y-dis); }printf("%d\n",ans); }else{ upda(x,y-val[x]);val[x]=y; } } } void dfs(int u,int fa,int d){ ol[++chuo][0]=u;dep[u]=d; in[u]=chuo; for(int i=0;i<g[u].size();++i){ int v=g[u][i]; if(v^fa) dfs(v,u,d+1),ol[++chuo][0]=u; } }inline void init(){ for(int j=1;(1<<j)<=chuo;++j) for(int i=1;i+(1<<j)-1<=chuo;++i) ol[i][j]=dep[ol[i][j-1]]>dep[ol[i+(1<<(j-1))][j-1]]?ol[i+(1<<(j-1))][j-1]:ol[i][j-1]; }inline int qu(int l,int r){ if(in[l]>in[r]) swap(l,r); int k=log2(in[r]-in[l]+1),lca;// lca=dep[ol[in[l]][k]]>dep[ol[in[r]-(1<<k)+1][k]]?ol[in[r]-(1<<k)+1][k]:ol[in[l]][k]; return dep[l]+dep[r]-dep[lca]*2; } void zx(int u,int fa){ siz[u]=1;int m1=0; for(int i=0;i<g[u].size();++i){ int v=g[u][i]; if(v^fa&&!vis[v]){ zx(v,u);siz[u]+=siz[v]; m1=max(m1,siz[v]); } }m1=max(m1,sum-siz[u]); if(m1<maxx){rt=u;maxx=m1;} }void csiz(int u,int fa){ siz[u]=1; for(int i=0;i<g[u].size();++i){ int v=g[u][i]; if(v^fa&&!vis[v]){ csiz(v,u);siz[u]+=siz[v]; } } }void dfs1(int u){ vis[u]=1; c[0][u].resize(siz[u]+2); c[1][u].resize(siz[u]+2); for(int i=0;i<g[u].size();++i){ int v=g[u][i]; if(!vis[v]){ maxx=sum=siz[v]; zx(v,u);fa[rt]=u; csiz(rt,-1);dfs1(rt); } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律