zoukankan      html  css  js  c++  java
  • 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;
     } 
    
    欢迎评论交流!
  • 相关阅读:
    leetcode题目19.删除链表的倒数第N个节点(中等)
    Android学习笔记---使用Service模仿下载效果
    Android学习笔记-简单聊天界面的实现
    Android学习笔记-ContentProvider操作
    Android高级-Android操作SQL数据管理,增删改查
    Android高级-正则表达式
    Android高级-SQL语言
    Android学习之路-录音功能实现
    gitee上传下载代码命令
    opencv进行视频播放每帧处理,读取视频失败
  • 原文地址:https://www.cnblogs.com/alking1001/p/11380678.html
Copyright © 2011-2022 走看看