容易证明,最终方案一定是某一个排列无限循环,那么就要满足$sum ai<=max(bi+ai)$,对所有数按照ai+bi排序后,枚举最大值,用权值线段树维护之前的ai最少要选几个
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 500005 4 #define ll long long 5 #define mid (l+r>>1) 6 int V,n,r,ans,f[N*40],ls[N*40],rs[N*40]; 7 ll sum[N*40]; 8 struct ji{ 9 ll a,b; 10 bool operator <(const ji &k)const{ 11 return a+b<k.a+k.b; 12 } 13 }a[N]; 14 void update(int &k,ll l,ll r,ll x){ 15 if (!k)k=++V; 16 if (l==r){ 17 f[k]++; 18 sum[k]+=x; 19 return; 20 } 21 if (x<=mid)update(ls[k],l,mid,x); 22 else update(rs[k],mid+1,r,x); 23 f[k]=f[ls[k]]+f[rs[k]]; 24 sum[k]=sum[ls[k]]+sum[rs[k]]; 25 } 26 int query(int k,ll l,ll r,ll x){ 27 if (!k)return 0; 28 if (l==r)return (x+l-1)/l; 29 if (sum[rs[k]]>=x)return query(rs[k],mid+1,r,x); 30 return f[rs[k]]+query(ls[k],l,mid,x-sum[rs[k]]); 31 } 32 int main(){ 33 scanf("%d",&n); 34 for(int i=1;i<=n;i++)scanf("%lld%lld",&a[i].a,&a[i].b); 35 sort(a+1,a+n+1); 36 ans=n+1; 37 for(int i=1;i<=n;i++){ 38 if (sum[1]>=a[i].b)ans=min(ans,query(r,1,1e12,a[i].b)+1); 39 update(r,1,1e12,a[i].a); 40 } 41 if (ans>n)ans=-1; 42 printf("%d",ans); 43 }