[湖南集训]谈笑风生

谈笑风生

题目大意:

给定a,求任何一个距 a 距离不超过给定的 k 的 b ,然后求一个 c 使得其为 a,b 的后代,求这样的三元组共有多少个。

数据结构好题啊!

解法分析:

我们可以深搜两遍(其实一遍也行),然后对于每个节点去权值线段树上跑一跑,记录 dfs 序,然后就成功地与江大大谈笑风生了。


//by Judge
#include<cstdio>
#include<iostream>
#define ll long long
#define mid (l+r>>1)
using namespace std;
const int M=3e5+7;
#ifndef Judge
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
char buf[1<<21],*p1=buf,*p2=buf;
inline int read(){ int x=0,f=1; char c=getchar();
	for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
	for(;isdigit(c);c=getchar()) x=x*10+c-'0'; return x*f;
} char sr[1<<21],z[20];int C=-1,Z;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
inline void print(ll x,char chr='\n'){
    if(C>1<<20)Ot();if(x<0)sr[++C]=45,x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]=chr;
} int n,m,q,p,k,pat,tim,cnt,le,ri,head[M],rt[M];
int dep[M],siz[M],dfn[M],L[M*21],R[M*21]; ll ans,sum[M*21];
struct Edge{ int to,next; }e[M<<1];
inline void add(int u,int v){
	e[++pat]={v,head[u]},head[u]=pat;
	e[++pat]={u,head[v]},head[v]=pat;
} void update(int las,int& now,int l,int r,int pos,int v){
	if(!now) now=++cnt; sum[now]=sum[las]+v; if(l==r) return ;
	if(pos<=mid) R[now]=R[las],update(L[las],L[now],l,mid,pos,v);
	else L[now]=L[las],update(R[las],R[now],mid+1,r,pos,v);
} ll query(int u,int v,int l,int r,int ql,int qr){
	if(l>qr||ql>r) return 0; if(ql<=l&&r<=qr) return sum[v]-sum[u];
	return query(L[u],L[v],l,mid,ql,qr)+query(R[u],R[v],mid+1,r,ql,qr);
} inline void cmax(int& a,int b){ if(a<b) a=b; }
#define v e[i].to
void prep(int u,int fa){
	siz[u]=1,dep[u]=dep[fa]+1,cmax(m,dep[u]);
	for(int i=head[u];i;i=e[i].next)
		if(v^fa) prep(v,u),siz[u]+=siz[v];
} void dfs(int u,int fa){ dfn[u]=++tim;
	update(rt[tim-1],rt[tim],1,m,dep[u],siz[u]-1);
	for(int i=head[u];i;i=e[i].next) if(v^fa) dfs(v,u);
}
int main(){ n=read(),q=read();
	for(int i=1,x,y;i<n;++i)
		x=read(),y=read(),add(x,y);
	for(prep(1,0),dfs(1,0);q;--q){
		p=read(),k=read(),le=dfn[p],ri=le+siz[p]-1;
		ans=query(rt[le],rt[ri],1,m,dep[p]+1,dep[p]+k);
		ans+=1ll*min(dep[p]-1,k)*(siz[p]-1),print(ans);
	} return Ot(),0;
}
posted @ 2018-11-15 15:01  Jμdge  阅读(258)  评论(0编辑  收藏  举报