P3899 谈笑风生 题解
link
solve
通过观察我们发现,a是固定不动的,而b距离a不超过k
则b有两种情况。
\((i)\) b 在 a 的上方
则 \(b\) 离 \(a\) 的距离最大为 \(min(deep[a],k)\)
\(c\) 就是 \(a\) 子树的任意一点。
则对答案的贡献就是 $min(deep[a],k)\times (size[a]-1) $
\((ii)\) b 是a 的下方
那我们b是a子树上距离 \(a\) 不超过 k 也就是深度差不超过k的一个点
\(c\) 就是 \(b\) 子树上的一个点
对答案的贡献就是把所有可能的 \(size[b]\) 加起来
我们以 \(deep[x]\) 为下标, \(size[x]\) 为权值建主席树,就可以统计出 \(sum\) 总和了。
注意一点,数据比较大,要开 long long
code
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
const int maxn=600005;
typedef long long LL;
int N,Q,son[maxn],nxt[maxn],lnk[maxn],cnt,deep[maxn],size[maxn],r[maxn],tot,q[maxn],l[maxn],sz,root[maxn];
struct data{
int l,r;
LL sum;
}tr[maxn*32];
inline int read(){
int ret=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
return ret*f;
}
int add_e(int x,int y){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;}
void dfs(int u,int fa){
l[u]=++tot;deep[u]=deep[fa]+1;q[tot]=u;size[u]=1;
for(int j=lnk[u];j;j=nxt[j]){
if(son[j]==fa)continue;
dfs(son[j],u);size[u]+=size[son[j]];
}
r[u]=tot;
}
void insert(int &x,int l,int r,int pos,int val){
tr[++sz]=tr[x];x=sz;
tr[x].sum+=(LL)val;
if(l==r)return ;
int mid=(l+r)>>1;
if(pos<=mid)insert(tr[x].l,l,mid,pos,val);
else insert(tr[x].r,mid+1,r,pos,val);
}
void update(int x){
int l=tr[x].l,r=tr[x].r;
tr[x].sum=tr[l].sum+tr[r].sum;
}
LL query(int i,int j,int l,int r,int ll,int rr){
if(ll<=l&&r<=rr)return tr[j].sum-tr[i].sum;
int mid=(l+r)>>1;
LL ans=0;
if (ll<=mid)ans+=query(tr[i].l,tr[j].l,l,mid,ll,rr);
if (rr>mid)ans+=query(tr[i].r,tr[j].r,mid+1,r,ll,rr);
return ans;
}
int main(){
freopen("3653.in","r",stdin);
freopen("3653.out","w",stdout);
N=read();Q=read();
for(int i=1;i<N;i++){
int x=read(),y=read();
add_e(x,y);add_e(y,x);
}
dfs(1,0);
for(int i=1;i<=N;i++)root[i]=root[i-1],insert(root[i],1,N,deep[q[i]],size[q[i]]-1);
for(int i=1;i<=Q;i++){
int x=read(),k=read();
LL t=query(root[l[x]],root[r[x]],1,N,deep[x]+1,deep[x]+k);
int len=min(k,deep[x]-1);
printf("%lld\n",t+(LL)len*(LL)(size[x]-1));
}
return 0;
}