您的位置:首页 > 其它

hdu 5877 离散化+树状数组+dfs序

2016-09-13 17:09 323 查看
点击打开链接

参考点击打开链接

第一个要求u 是v 的祖先,那么可以dfs,遍历到v时,要使上方的都是满足第一条件的u,即遍历完某个节点u的子树时,这时u不可能是任何节点的祖先 删除u的影响,这样就能保证所有有影响的都是祖先。要求w[u]*w[v]<=k,那么到v的时候,所有小于等于k/w[v]的u都满足,可以想到树状数组。结点的值最大10亿,肯定要离散化,离散化的时候要把k/w[v]加进去一起离散。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
const int inf=1<<20;
const int M = 1e6+5;
vector<int> e[M];
int vis[M];
int in[M];//in[i]为0的为root
long long n,k;
long long a[M*2];
long long c[M<<1];
long long ans,data[2*M];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int val)
{
while(x<2*n)
{
c[x]+=val;
x+=lowbit(x);//往右上走
}
}
int sum(int x)
{
int s=0;
while(x>0)
{
s+=c[x];
x-=lowbit(x);
}
return s;
}
void dfs(int rt)
{
vis[rt]=1;

ans+=sum(a[rt+n]);//在它之前进入的都为它的祖先(兄弟节点在遍历完之后已经删除)

update(a[rt],1);
//au*av<=k 祖先节点要满足au<=k/a[v]
for(int i=0;i<e[rt].size();i++)
{
int son=e[rt][i];
if(!vis[son])
{
dfs(son);
}
}
update(a[rt],-1);//该节点的子树全都遍历完了 该节点不是任何节点的祖先时 删除该节点的值
}
void prepare(long long *x) //离散化模板
{
for(int i=1;i<=2*n;i++) data[i]=x[i];
sort(data+1,data+2*n+1);
int m=unique(data+1,data+2*n+1)-data-1;
for(int i=1;i<=2*n;i++) x[i]=lower_bound(data+1,data+m+1,x[i])-data;
}
int main()
{
int t;
cin>>t;
while(t--)
{
cin>>n>>k;
ans=0;
memset(in,0,sizeof(in));
memset(c,0,sizeof(c));
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)
{
e[i].clear();
}
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
if(a[i]==0)
a[i+n]=M;
else
a[i+n]=k/a[i];

}
prepare(a);//数据a[i]<=10^9 n<=10^5 数据离散化使a[i]的范围中10^5内
//使得树状数组的空间不溢出

for(int i=1;i<=n-1;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
in[v]++;
}
int root;
for(int i=1;i<=n;i++)
{
if(!in[i])
{
root=i;
break;
}
}
dfs(root);
cout<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: