[BZOJ3653][长链剖分]谈笑风生

BZOJ3653

我也不知道题面的引申意义

发现可以求出以每个点为p时的ans,讨论一下祖先和子孙的贡献,用长链剖分维护就好了

Code:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline int read(){
	int res=0,f=1;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-') f=-f;ch=getchar();}
	while(isdigit(ch)) {res=(res<<1)+(res<<3)+(ch^48);ch=getchar();}
	return res*f;
}
const int N=3e5+5;
int vis[N<<1],nxt[N<<1],head[N<<1],tot=0;
int val[N],pt[N],fa[N],lson[N],top[N],md[N],dep[N],siz[N];
ll tmp[N],*f[N],*id=tmp,ans[N];
struct Q{int num,k;};
vector<Q>q[N];
inline void add(int x,int y){vis[++tot]=y;nxt[tot]=head[x];head[x]=tot;}
void dfs(int v){
	pt[v]=siz[v]=1;
	for(int i=head[v];i;i=nxt[i]){
		int y=vis[i];
		if(pt[y]) continue;
		fa[y]=v;md[y]=dep[y]=dep[v]+1;
		dfs(y);
		siz[v]+=siz[y];
		if(md[y]>md[lson[v]]) lson[v]=y;
	}
	if(lson[v]) md[v]=md[lson[v]];
}
void dp(int v){
	f[v][0]=siz[v]-1;
	if(lson[v]) f[lson[v]]=f[v]+1,dp(lson[v]),f[v][0]+=f[lson[v]][0];
	for(int i=head[v];i;i=nxt[i]){
		int y=vis[i];
		if(y==fa[v] || y==lson[v]) continue;
		f[y]=id;id+=md[y]-dep[y]+1;
		dp(y);
		for(int j=0;j<=md[y]-dep[y];j++) f[v][j+1]+=f[y][j];
		f[v][0]+=f[y][0];
	}
	for(int i=q[v].size()-1;~i;i--){
		int k=q[v][i].k,num=q[v][i].num;
		ans[num]+=1ll*(siz[v]-1)*min(dep[v]-1,k);
		if(k>=md[v]-dep[v]) ans[num]+=f[v][0]-siz[v]+1;
		else ans[num]+=f[v][0]-siz[v]+1-f[v][k+1];
	}
	return;
}
int n,m;
int main(){
	n=read(),m=read();
	for(int x,y,i=1;i<n;i++){x=read(),y=read();add(x,y);add(y,x);}
	dep[1]=1;dfs(1);
	for(int i=1;i<=m;i++) {int u=read();Q t;t.k=read();t.num=i;q[u].push_back(t);}
	f[1]=id;id+=md[1];dp(1);
	for(int i=1;i<=m;i++) cout<<ans[i]<<"\n";
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值