线段树合并 WA成24分 求查错 悬赏1关注
查看原帖
线段树合并 WA成24分 求查错 悬赏1关注
743811
Shakespeare07楼主2022/11/16 17:01

rt.

只有前4个点时对的

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+5;
int n,m,e;
int to[N<<1],ne[N<<1],h[N];
void add(int x,int y){
	to[++e]=y,ne[e]=h[x],h[x]=e;
}
int dep[N],sz[N];
int lc[N<<6],rc[N<<6],cnt[N<<6],rt[N],tot;
void pu(int x){
	cnt[x]=cnt[lc[x]]+cnt[rc[x]];
}
void update(int &p,int ll,int rr,int x,int d){
	p=++tot;
	if(ll==rr){
		cnt[p]+=d;
		return;
	}
	int mid=ll+rr>>1;
	if(x<=mid) update(lc[p],ll,mid,x,d);
	else update(rc[p],mid+1,rr,x,d);
	pu(x);
}
int merge(int x,int y,int ll,int rr){
	if(!x || !y) return x+y;
	int now=++tot;
	if(ll==rr){
		cnt[now]=cnt[x]+cnt[y];
		return now;
	}
	else{
		int mid=ll+rr>>1;
		lc[now]=merge(lc[x],lc[y],ll,mid);
		rc[now]=merge(rc[x],rc[y],mid+1,rr);
	}
	pu(now);
	return now;
}
int query(int p,int ll,int rr,int l,int r){
	if(!p) return 0;
	if(ll>=l && rr<=r) return cnt[p];
	int mid=ll+rr>>1,ans=0;
	if(l<=mid) ans+=query(lc[p],ll,mid,l,r);
	if(r>mid) ans+=query(rc[p],mid+1,rr,l,r);
	return ans;
}
void dfs(int x,int fa){
	dep[x]=dep[fa]+1,sz[x]=1;
	for(int i=h[x];i;i=ne[i]){
		int y=to[i];
		if(y==fa) continue;
		dfs(y,x);
		sz[x]+=sz[y];
	}
	update(rt[x],1,n,dep[x],sz[x]-1);
	for(int i=h[x];i;i=ne[i]){
		int y=to[i];
		if(y==fa) continue;
		rt[x]=merge(rt[x],rt[y],1,n);
	}
}
signed main(){
	cin>>n>>m;
	for(int i=1;i<n;++i){
		int x,y;cin>>x>>y;
		add(x,y),add(y,x);
	}
	dfs(1,0);
	while(m--){
		int u,k;cin>>u>>k;
		int ans=min(dep[u]-1,k)*(sz[u]-1);
		ans+=query(rt[u],1,n,dep[u]+1,dep[u]+k);
		cout<<ans<<endl;
	}
	return 0;
}
2022/11/16 17:01
加载中...