首页 > 代码库 > 【树状数组】Gym - 101147J - Whistle's New Car

【树状数组】Gym - 101147J - Whistle's New Car

题意就是对每个点i,统计在其子树内(不含自身),且depj-depi<=xj的点有多少个。

把点分别按照dep-x和dep进行排序,离线处理,

每次把dep-x小于等于当前dep值的点插入树状数组,就变成了询问dfs序在一个区间内的点有多少个,可以用树状数组轻松解决。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int f,C;
void R(int &x){
    C=0;f=1;
    for(;C<‘0‘||C>‘9‘;C=getchar())if(C==‘-‘)f=-1;
    for(x=0;C>=‘0‘&&C<=‘9‘;C=getchar())(x*=10)+=(C-‘0‘);
    x*=f;
}
typedef long long ll;
#define N 500010
int T,n,a[N];
int v[N<<1],next[N<<1],w[N<<1],first[N],e;
void AddEdge(int U,int V,int W)
{
	v[++e]=V;
	w[e]=W;
	next[e]=first[U];
	first[U]=e;
}
ll dep[N];
int Ls[N],Rs[N],tot;
bool vis[N];
void dfs(int U)
{
	vis[U]=1;
	Ls[U]=++tot;
	for(int i=first[U];i;i=next[i])
	  if(!vis[v[i]])
	    {
	      dep[v[i]]=dep[U]+(ll)w[i];
	      dfs(v[i]);
	    }
	Rs[U]=tot;
}
//struct Point
//{
//	ll v;
//	int p;
//}t[N<<1];
//bool cmp(const Point &a,const Point &b)
//{
//	return a.v<b.v;
//}
struct Poin2
{
	ll v;
	int p;
}all[N<<1];
bool cm2(const Poin2 &a,const Poin2 &b)
{
	return a.v<b.v;
}
int anss[N];
int d[N];
void update(int p){for(;p<=n;p+=(p&(-p))) ++d[p];}
int query(int p){int res=0; for(;p;p-=(p&(-p))) res+=d[p]; return res;}
int main()
{
	freopen("car.in","r",stdin);
//	freopen("car.out","w",stdout);
	int x,y,z;
	R(T);
	for(;T;--T)
	  {
	  	e=tot=0;
	  	memset(v,0,sizeof(v));
	  	memset(w,0,sizeof(w));
	  	memset(next,0,sizeof(next));
	  	memset(first,0,sizeof(first));
	  	memset(vis,0,sizeof(vis));
	  	memset(dep,0,sizeof(dep));
	  	memset(d,0,sizeof(d));
	  	R(n);
	  	for(int i=1;i<=n;++i)
	  	  R(a[i]);
	  	for(int i=1;i<n;++i)
	  	  {
	  	  	R(x); R(y); R(z);
	  	  	AddEdge(x,y,z);
	  	  	AddEdge(y,x,z);
	  	  }
	  	dfs(1);
//	  	for(int i=1;i<=n;++i)
//	  	  {
//	  	  	t[i].v=dep[i]-(ll)a[i];
//	  	  	t[i].p=i;
//	  	  }
//	  	for(int i=n+1;i<=n*2;++i)
//	  	  {
//	  	  	t[i].v=dep[i-n];
//	  	  	t[i].p=i;
//	  	  }
//	  	sort(t+1,t+n*2+1,cmp);
//	  	int zy=1;
//	  	all[t[1].p].v=zy;
//	  	all[t[1].p].p=(t[1].p>n ? t[1].p-n : t[1].p);
//	  	for(int i=2;i<=n*2;++i)
//	  	  {
//	  	  	if(t[i].v!=t[i-1].v)
//	  	  	  ++zy;
//	  	  	all[t[i].p].v=zy;
//	  		all[t[i].p].p=(t[i].p>n ? t[i].p-n : t[i].p);
//	  	  }
	  	for(int i=1;i<=n;++i)
	  	  {
	  	  	all[i].v=dep[i]-(ll)a[i];
	  	  	all[i].p=i;
	  	  }
	  	for(int i=n+1;i<=n*2;++i)
	  	  {
	  	  	all[i].v=dep[i-n];
	  	  	all[i].p=i-n;
	  	  }
	  	sort(all+1,all+n+1,cm2);
	  	sort(all+n+1,all+n*2+1,cm2);
	  	int j=1;
	  	for(int i=n+1;i<=n*2;++i)
	  	  {
	  	  	while(all[j].v<=all[i].v && j<=n)
	  	  	  {
	  	  	  	update(Ls[all[j].p]);
	  	  	  	++j;
	  	  	  }
	  	  	anss[all[i].p]=query(Rs[all[i].p])-query(Ls[all[i].p]);
	  	  }
	  	for(int i=1;i<n;++i)
	  	  printf("%d ",anss[i]);
	  	printf("%d\n",anss[n]);
	  }
	return 0;
}

【树状数组】Gym - 101147J - Whistle's New Car