线段树合并T成60求助
查看原帖
线段树合并T成60求助
167279
Danno0v0楼主2022/10/21 09:18
#include<bits/stdc++.h>
#define ls(x) tree[x].l
#define rs(x) tree[x].r
#define Max 1000001
using namespace std;
struct node
{
	int tot,l,r;
}tree[1<<26];
struct q
{
	int id,k;
};
vector<q>ques[Max];
int cnt;
int fi[Max],nx[Max],to[Max],tot;
int depth[Max],size[Max];
int n,q,ans[Max];
int root[Max];
int link(int a,int b)
{
	nx[++tot]=fi[a];
	fi[a]=tot;
	to[tot]=b;
}
void update(int x)
{
	tree[x].tot=0;
	if(ls(x)) tree[x].tot+=tree[ls(x)].tot;
	if(rs(x)) tree[x].tot+=tree[rs(x)].tot;
}
void change(int x,int b,int k,int L,int R)
{
	if(L==R&&L==b)
	{
		tree[x].tot+=k;
		return;	
	}
	int M=(L+R)>>1;
	if(b<=M)
	{
		if(!ls(x)) ls(x)=++cnt;
		change(ls(x),b,k,L,M);
	}
	else
	{
		if(!rs(x)) rs(x)=++cnt;
		change(rs(x),b,k,M+1,R);
	}
	update(x);
}
int query(int x,int l,int r,int L,int R)
{
	if(l<=L&&R<=r)
		return tree[x].tot;
	int M=(L+R)>>1,ans=0;
	if(l<=M&&ls(x)) ans+=query(ls(x),l,r,L,M);
	if(M<R&&rs(x)) ans+=query(rs(x),l,r,M+1,R);
	return ans;
}
int Merge(int x,int y,int L,int R)
{
	if(!y) return x;
	if(!x) return y;
	if(L==R)
	{
		tree[x].tot+=tree[y].tot;
		return x;
	}
	int M=(L+R)>>1;
	ls(x)=Merge(ls(x),ls(y),L,M);
	rs(x)=Merge(rs(x),rs(y),M+1,R);
	update(x);
	return x;
}
void dfs(int x,int fath)
{
	root[x]=++cnt;
	size[x]=1;
	for(int i=fi[x];i;i=nx[i])
	{
		int v=to[i];
		if(v!=fath)
			depth[v]=depth[x]+1,dfs(v,x),size[x]+=size[v],root[x]=Merge(root[x],root[v],1,n);
	}
	for(int i=0;i<ques[x].size();i++)
	{
		int id=ques[x][i].id,k=ques[x][i].k;
		ans[id]+=min(k,depth[x]-1)*(size[x]-1)+query(root[x],depth[x]+1,depth[x]+k,1,n);
	}
	change(root[x],depth[x],size[x]-1,1,n);
}
int main()
{
	int x,y;
	cin>>n>>q;
	for(int i=1;i<n;i++)
		cin>>x>>y,link(x,y),link(y,x);
	for(int i=1;i<=q;i++)
		cin>>x>>y,ques[x].push_back({i,y});
	depth[1]=1;
	dfs(1,0);
	for(int i=1;i<=q;i++)
		cout<<ans[i]<<endl;
}
2022/10/21 09:18
加载中...