题意就是对每个点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;
}

最新文章

  1. cocos2dx 3.2 Touch Listen和menu回调实现截屏
  2. CentOS 安装rz和sz命令
  3. kernel update 2.6.18-2.6.38
  4. Carthage 安装和使用
  5. windbg常用命令
  6. javascript的模块化解读
  7. HUD加载动画支持gif
  8. C++对象数组操作误区
  9. 【转】android:DDMS查看Threads--不错
  10. SQL Server2005使用CTE实现递归
  11. day6(列表操作、列表练习题)
  12. Python使用wmi获取Windows相关信息
  13. sonar结合jenkins
  14. 学以致用十八-----shell脚本之基础概念及变量
  15. Linux下简单线程池的实现
  16. Vue-router浅析(二)
  17. 一、think in java 第一章
  18. 【CF954I】Yet Another String Matching Problem(FFT)
  19. request机制
  20. GNU C编译器的gnu11和c11

热门文章

  1. 如何优化JQuery each()函数的性能
  2. 把java的class文件打成jar包的步骤
  3. Linux重定向: &gt; 和 &amp;&gt; 区别
  4. SQLyog 使用笔记,自增主键数据冲突错误
  5. 数据结构之DFS与BFS
  6. fs.watch 爬坑
  7. javascript简易下拉菜单效果
  8. bootstrap再次回顾认识到的东西
  9. Git菜鸟
  10. 【CF1023E】Down or Right(交互,贪心)