CF Hello World 2018 913D SOL

题目大意:

 给你X门学科,每一门学科有两个参数,ti和·ai,我们想通过一门学科只有满足以下2个条件:

  1.其尝试考试的simga ti <=T;

  2.其尝试考试的次数<=ai

求最多通过的学科数,并输出方案。

SOL:

 我们发现如果我们有考试却没有通过,我们还不如不考。

 我们又发现其满足二分性质。那么我们就二分答案。

#include<bits/stdc++.h>
#define sight(c) ('0'<=c&&c<='9')
#define N 400007
inline void read(int &x){
    static char c;static int b;
    for (b=1,c=getchar();!sight(c);c=getchar())if (c=='-') b=-1;
    for (x=0;sight(c);c=getchar()) x=x*10+c-48;
    x*=b;
}
struct Node{
    int a,t,id;
    bool operator < (const Node& T)const {
       return t<T.t;
    }
}t[N];
using namespace std;
int T,n,r,ans,Ans,tot;
inline bool check(int x){
    tot=Ans=0;
    for (int i=1;i<=n;i++) if (t[i].a>=x)  {
        Ans+=t[i].t;tot++; if (tot==x) break;
    }
    return tot==x&&Ans<=T;
}
int main () {
    //freopen("a.in","r",stdin);
    read(n); read(T);
    for (int i=1;i<=n;i++) read(t[i].a),read(t[i].t),t[i].id=i;
    r=trunc(log2(n));r=1<<r;
    sort(t+1,t+n+1);
    while (r) {
        if (check(ans+r)) ans+=r; r>>=1; 
    }
    printf("%d
",ans);
    printf("%d
",ans); tot=0;
    if (!ans) return 0;
    for (int i=1;i<=n;i++) {
     if(t[i].a>=ans) {printf("%d ",t[i].id);tot++;}
     if (tot==ans)  break;
    } return 0;
}
原文地址:https://www.cnblogs.com/rrsb/p/8260814.html