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;
}