• Weak Pair (dfs+树状数组)


    Weak Pair (dfs+树状数组)

    题意

    这个题目是要求:一颗树上,有n个节点,给出每个节点的权值。另外给出一个值k,问有多少对节点满足:

    • (power[u]*power[v]<=k)
    • u是v节点的祖先(u不等于v)

    解题思路

    这个可以找父节点权值满足小于或者等于(frac{k}{power[v]})(注意这里可能不能够整除)

    我们从根节点出发,一个一个地遍历,走到一个节点就看它前面的父节点有没有符合条件的。这个可以使用树状数组来进行求解,在已经去完重和排好序的数组中查找满足条件节点的位置,和当前节点的位置,注意这里使用的是upper_bound,因为上面的条件可能不能够整除,使用lower_bound不够精确。

    代码实现

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const ll inf=1e18;
    const int maxn=1e5+7;
    vector<int> g[maxn];
    int sum[maxn];
    ll power[maxn];
    ll lishan[maxn];
    int vis[maxn];
    int n, cnt, ans;
    ll k;
    int lowbit(int x)
    {
    	return x&(-x);
    }
    int update(int x, int v)
    {
    	while(x<=cnt+1)
    	{
    		sum[x]+=v;
    		x+=lowbit(x);
    	}
    }
    int getsum(int x)
    {
    	int ret=0;
    	while(x>0)
    	{
    		ret+=sum[x];
    		x-=lowbit(x);
    	}
    	return ret;
    }
    void dfs(int rt)
    {
    	int len=g[rt].size();
    	int pos;
    	
    	if(power[rt]==0) pos=cnt+1;
    	else pos=upper_bound(lishan+1, lishan+cnt+1, k/power[rt])-(lishan);
    	
    	int posthis=upper_bound(lishan+1, lishan+cnt+1, power[rt])-(lishan);
    	
    	ans+=getsum(pos);
    	update(posthis, 1);
    	for(int i=0; i<len; i++)
    	{
    		dfs(g[rt][i]);
    	}
    	update(posthis, -1);
    }
    void init()
    {
    	ans=0;
    	for(int i=0; i<=n; i++)
    	{
    		vis[i]=0;
    		g[i].clear();
    		sum[i]=0;
    	}
    }
    int main()
    {
    	int t;
    	scanf("%d", &t);
    	while(t--)
    	{
    		scanf("%d%lld", &n, &k);
    		init();
    		for(int i=1; i<=n; i++)
    		{
    			scanf("%lld", &power[i]);
    			lishan[i]=power[i];
    		}
    		sort(lishan+1, lishan+n+1);
    		cnt=unique(lishan+1, lishan+n+1)-(lishan+1);
    		int a, b;
    		for(int i=1; i<n; i++)
    		{
    			scanf("%d%d", &a, &b);
    			g[a].push_back(b);
    			vis[b]=1;
    		}
    		for(int i=1; i<=n; i++)
    		{
    			if(!vis[i])
    			{
    				dfs(i);
    				break;
    			}
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
     } 
    
    欢迎评论交流!
  • 相关阅读:
    在Ubuntu下使用命令删除目录
    Visual Studio添加lib到链接依赖项的几种方法
    svn回到某个历史版本的做法
    iOS菜鸟成长笔记(3)——斯坦福公开课学习(1)
    VS自定义开发向导中的vsdir文件的简单说明
    OpenGL编程逐步深入(十一)组合变换
    iOS菜鸟成长笔记(2)——网易彩票练习
    AngularJs轻松入门(九)与服务器交互
    AngularJs轻松入门(八)Cookies读写
    AngularJs轻松入门(七)多视图切换
  • 原文地址:https://www.cnblogs.com/alking1001/p/11380678.html
Copyright © 2020-2023  润新知