Doremy‘s Connecting Plan(cf 906 div2)

Doremy生活在一个由编号从1到n的n个城市组成的国家,第二个城市居住着ai人。它可以被建模为具有n节点的无向图。最初,图形中没有边。现在Doremy想要使图连通。

要做到这一点,她可以在i和j之间添加一条边,并且满足以下条件

其中S是当前在i或j的同一连通分量中的所有节点的集合,c是给定的常数。Doremy能把图连接起来吗?如果存在从i到j的路径,则两个节点(i,j)在同一连通分量中。如果图的所有节点都在同一个连接的组件中,则图是连接的。

多组输入 t(1≤t≤10^4)

输入 第一行输入  n, c (2≤n≤2*10^5, 1≤c≤10^6)

输出 可以输出 Yes 否则 No

输入样例  

7
4 10
0 20 15 10
2 1
1 1
5 1
0 1 0 4 199
5 2
1 1 3 1 1
5 5
5 6 1 10 2
5 1000000
1000000000000 1000000000000 1000000000000 1000000000000 1000000000000
3 1
0 0 2 

输出样例 

Yes
Yes
Yes
No
No
Yes
No 

思路: 

假设存在2个大于1的下标i,j 初始时它们满足

ai+aj>=i*j*c

证明 ai和aj至少存在一个点,可以和a1相连

反证法:

假设ai和aj都不能与a1相连

那么

ai+aj>=i*j*c

ai+a1<i*c

aj+a1<j*c

从而推出

2*a1+ai+aj<(i+j)*c

则 i*j*c<(i+j)*c

i*j<(i+j)

i<j/(j-1)<1+1/(j-1)<=2

j<i/(i-1)<1+1/(i-1)<=2

与i>2矛盾

所以优先取a1 与其他点相连

a1+aj>=1*j*c

则 a1>=j*c-aj

则 sum>=j*c-aj(即可 若不行 则 No 应该从小到大取弄 )

j*c-aj从小到大排序

如果 sum<j*c-aj  这使这个数不符合条件 sum不加上a[j] 往后j*c-aj的值越来越大 肯定也是不可能找到比它小的值了 故输出No

#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+10;
pair<ll,ll>p[N];
ll a[N];
int main()
{
	int t;cin>>t;
	while(t--)
	{
		ll n,c;cin>>n>>c;
		
		for(int i=1;i<=n;i++) cin>>a[i];
		for(int i=2;i<=n;i++)
		{
			p[i].first=i*c-a[i];
			p[i].second=i;
		}
		sort(p+2,p+1+n);
		ll sum=a[1];
		int flag=1;

		for(int i=2;i<=n;i++)
		{
		    ll num=p[i].first,num1=p[i].second;
			if(sum<num)
			{
				flag=0;
				break;
				}	
			else
			{
				sum+=a[num1];
			}
		}
		if(!flag) cout<<"No"<<endl;
		else cout<<"Yes"<<endl;
		
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值