您的位置:首页 > 其它

HDU 5877 [dfs序][线段树][序]

2016-09-23 16:23 357 查看
/*
题意:
n个点的树,每个点给定一个权值,给定一个k,求任意一点的子树中,权值小于k/该点权值的点共有多少个。
思路:
1.很明显的子树的操作,应用dfs序。
2.比赛的时候傻逼了,一直在调划分树。实际上这题考虑序关系,加树状数组或者线段树就可以搞定了。
3.序关系:将权值按照从大到小的顺序排序进行查询,然后按照从小到大的顺序排序进行插入。
*/

#include<bits/stdc++.h>
#define N 100050
using namespace std;
int ednum;
struct edge{
int id;
edge *next;
};
edge edges
;
edge *adj
;
struct tr{
int s,e,num;
};
tr tree[N*4];
void build(int s,int e,int k){
tr &tmp=tree[k];
tmp.s=s;tmp.e=e;tmp.num=0;
if(s==e)return;
int mid=(s+e)>>1;
build(s,mid,k<<1);
build(mid+1,e,k<<1|1);
}
int cha(int s,int e,int k){
tr &tmp=tree[k];
if(tmp.s==s&&tmp.e==e)return tmp.num;
int mid=(tmp.s+tmp.e)>>1;
if(e<=mid)return cha(s,e,k<<1);
else if(s>mid)return cha(s,e,k<<1|1);
else return cha(s,mid,k<<1)+cha(mid+1,e,k<<1|1);
}
void ins(int pos,int k){
tr &tmp=tree[k];
if(tmp.s==tmp.e){
tmp.num++;
return;
}
int mid=(tmp.s+tmp.e)>>1;
if(pos<=mid)ins(pos,k<<1);
else ins(pos,k<<1|1);
tmp.num=tree[k<<1].num+tree[k<<1|1].num;
}
inline void addedge(int a,int b){
edge *tmp=&edges[ednum++];
tmp->id=b;
tmp->next=adj[a];
adj[a]=tmp;
}
struct st{
int id;
long long val;
};
bool cmp1(st a,st b){
return a.val<b.val;
}
bool cmp2(st a,st b){
return a.val>b.val;
}
st sol1
,sol2
;
long long jilu
;
int from
;
int id
,siz
;
int dfn;
void dfs(int pos){
id[pos]=dfn++;
siz[pos]=1;
for(edge *it=adj[pos];it;it=it->next){
dfs(it->id);
siz[pos]+=siz[it->id];
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
memset(adj,NULL,sizeof(adj));
memset(from,0,sizeof(from));
ednum=0;
int n;
long long k;
scanf("%d%lld",&n,&k);
build(1,n,1);
for(int i=1;i<=n;i++){
scanf("%lld",jilu+i);
sol1[i].id=i;
sol1[i].val=jilu[i];
sol2[i]=sol1[i];
}
sort(sol1+1,sol1+1+n,cmp1);
sort(sol2+1,sol2+1+n,cmp2);
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
addedge(a,b);
from[b]=a;
}
int st=1;
while(from[st]){
st=from[st];
}
dfn=1;
dfs(st);
int bf=1;
long long ans=0;
for(int i=1;i<=n;i++){
while(bf<=n&&sol1[bf].val<=k/sol2[i].val){
ins(id[sol1[bf].id],1);
bf++;
}
ans+=cha(id[sol2[i].id],id[sol2[i].id]+siz[sol2[i].id]-1,1);
ans-=cha(id[sol2[i].id],id[sol2[i].id],1);
}
printf("%lld\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: