• [noi795]保镖


    容易证明,最终方案一定是某一个排列无限循环,那么就要满足$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
  • 相关阅读:
    docker安装
    linux磁盘空间挂载
    python之MD5加密
    python之pymysql
    python 之Redis笔记
    python 随机生成中文名字
    python之json笔记
    python时间模块笔记
    python 用pip安装pymysql(win7下)
    数据库操作番外篇~
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/11750184.html
Copyright © 2020-2023  润新知