首页 > 其他 > 详细

[noi795]保镖

时间:2019-10-28 09:53:56      阅读:82      评论:0      收藏:0      [点我收藏+]

容易证明,最终方案一定是某一个排列无限循环,那么就要满足$\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 }
View Code

 

[noi795]保镖

原文:https://www.cnblogs.com/PYWBKTDA/p/11750184.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!