求调线段树合并!!!(样例都过了)
查看原帖
求调线段树合并!!!(样例都过了)
89441
huang_jr楼主2022/7/9 17:19
#include <bits/stdc++.h>
using namespace std;

inline int read()
{
	int f=1,s=0;
	char c=getchar();
	for (;(c<'0'||c>'9')&&c!='-';c=getchar());
	if (c=='-')
	{
		f=-1;
		c=getchar();
	}
	for (;c>='0'&&c<='9';c=getchar())
		s=(s<<1)+(s<<3)+c-48;
	return s*f;
}

inline void write(int x)
{
	if (x<0)
		x=-x,putchar('-');
	if (x>9)
		write(x/10);
	putchar(x%10+48);
}

typedef struct{
	int next,to;
}E;

const int MAX=100005;
E edge[MAX<<1];
int n,m;
int head[MAX],tot;
int tree[MAX<<5],ls[MAX<<5],rs[MAX<<5],root[MAX],cnt;
int x,y;

inline void add(long long x,long long y)
{
	edge[++tot].to=y;
	edge[tot].next=head[x];
	head[x]=tot;
}

inline void insert(int &i,int l,int r,int k)
{
	i=++cnt;
	tree[i]++;
	if (l==r)
		return;
	int mid=(l+r)>>1;
	if (k<=mid)
		insert(ls[i],l,mid,k);
	else
		insert(rs[i],mid+1,r,k);
}

inline void merge(int &x,int y,int l,int r)
{
	if (!x||!y)
	{
		x+=y;
		return;
	}
	if (l==r)
	{
		tree[x]+=tree[y];
		return;
	}
	int mid=(l+r)>>1;
	merge(ls[x],ls[y],l,mid);
	merge(rs[x],rs[y],mid+1,r);
	tree[x]=tree[ls[x]]+tree[rs[x]];
}

inline int query(int i,int l,int r,int k)
{
	int sum=0;
	if (l==r)
	{
		if (tree[i]>=k)
			return 1;
		else
			return 0;
	}
	int mid=(l+r)>>1;
	if (tree[ls[i]]>=k)
		sum+=query(ls[i],l,mid,k);
	if (tree[rs[i]]>=k)
		sum+=query(rs[i],mid+1,r,k);
	return sum;
}

inline void dfs(int x,int fa)
{
	for (int i=head[x];i;i=edge[i].next)
	{
		int node=edge[i].to;
		if (node==fa)
			continue;
		dfs(node,x);
		merge(root[x],root[node],1,MAX);
	}
}

int main()
{
	n=read(),m=read();
	for (int i=1;i<=n;i++)
	{
		x=read();
		insert(root[i],1,MAX,x);
	}
	for (int i=1;i<n;i++)
	{
		x=read(),y=read();
		add(x,y),add(y,x);
	}
	dfs(1,0);
	for (int i=1;i<=m;i++)
	{
		x=read(),y=read();
		write(query(root[x],1,MAX,y)),puts("");
	}
	return 0;
}
2022/7/9 17:19
加载中...