
HMF-have much fun Site
文章
标签
16

阅

【题解】P6626 [省选联考 2020 B 卷] 消息传递
热度: loading...
模板题。
询问形如对一个点求距离它为 的点有多少个,典型的与树形态无关的问题,考虑点分治。
将询问挂到点上,每次对于分支中心 dfs,记录下距离分治中心为 的点的总数,再记录下距离分治中心为 ,且在分治中心的儿子 子树里的点的总数。答案为与询问点在不同子树中,且距离分治中心为询问距离减去询问点到分治中心距离的点。设询问点到分治中心的距离为 ,考虑容斥,总答案为距离询问中心距离为 的点的总数减去与询问点在同一子树内且距离分治中心为 的点的总数,用 map 统计即可。
#include<bits/stdc++.h>
#define N 100010
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
int T,n,m;
typedef pair<int,int> pii;
int read() {
int res=0,f=1;char ch=getchar();
while(!isdigit(ch)) f=ch=='-'?-1:1,ch=getchar();
while(isdigit(ch)) res=res*10+ch-'0',ch=getchar();
return f*res;
}
int cnt,head[N],to[N<<1],nxt[N<<1];
vector<pii> qu[N];
int vis[N],siz[N],son[N],rt,S,ans[N];
void insert(int u,int v){
cnt++;
to[cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
}
void gtrt(int now,int fa) {
// cout<<now<<endl;
siz[now]=1,son[now]=0;
for(int i=head[now]; i; i=nxt[i])
if(!vis[to[i]]&&to[i]!=fa) {
gtrt(to[i],now);
siz[now]+=siz[to[i]];
son[now]=max(son[now],siz[to[i]]);
}
son[now]=max(son[now],S-siz[now]);
if(son[now]<son[rt]) rt=now;
}
struct node{
int dis,id,fr;
bool operator <(const node o) const{return dis==o.dis?fr<o.fr:dis<o.dis;}
}sk[N],q[N];
int tp,qn,bac[N];
map<pii,int> cot;
void dfs(int now,int fa,int dis,int fr) {
cot[mp(fr,dis)]++,bac[dis]++;
for(int i=0,sz=qu[now].size(); i<sz; i++) q[++qn]=node{qu[now][i].fi-dis,qu[now][i].se,fr};
for(int i=head[now]; i; i=nxt[i])
if(!vis[to[i]]&&to[i]!=fa) dfs(to[i],now,dis+1,(fr==0)?to[i]:fr);
}
void clean(int now,int fa,int dis) {
bac[dis]--;
for(int i=head[now]; i; i=nxt[i])
if(!vis[to[i]]&&to[i]!=fa) clean(to[i],now,dis+1);
}
void solve(int now) {
vis[now]=1;
tp=qn=0,cot.clear(),dfs(now,0,0,0);
for(int i=1; i<=qn; i++) if(q[i].dis>=0)
ans[q[i].id]+=bac[q[i].dis]-cot[mp(q[i].fr,q[i].dis)];
clean(now,0,0);
int tmp=S;
for(int i=head[now]; i; i=nxt[i]) if(!vis[to[i]]) {
S=siz[to[i]]<siz[now]?siz[to[i]]:tmp-siz[now];
rt=0,gtrt(to[i],now),solve(rt);
}
}
int main()
{
T=read();
while(T--) {
cnt=0;
for(int i=1; i<=n; i++) qu[i].clear();
memset(vis,0,sizeof(vis));
memset(ans,0,sizeof(ans));
memset(head,0,sizeof(head));
n=read(),m=read();
for(int i=1; i<n; i++) {
int u=read(),v=read();
insert(u,v);
insert(v,u);
}
for(int i=1; i<=m; i++) {
int x=read(),k=read();
if(!k) ans[i]=1;
else qu[x].pb(mp(k,i));
}
son[0]=S=n,rt=0,gtrt(1,0),solve(rt);
for(int i=1; i<=m; i++) cout<<ans[i]<<endl;
}
}
赏
