1. 程式人生 > >[NOIP10.6模擬賽]1.merchant題解--思維+二分

[NOIP10.6模擬賽]1.merchant題解--思維+二分

函數 這樣的 分析 cpp 等於 read type reat gis

題目鏈接:

while(1)gugu(while(1))

閑扯

考場上怕T2正解寫掛其他兩題沒管只打了暴力,晚上發現這題思維挺妙的

同時想吐槽出題人似乎熱衷卡常...我的巨大常數現在顯露無疑QAQ

分析

這道題yy出了一個似乎比solution更好理解的解法,一開始有\(n\)條一次函數,就有\(2^n\)種函數集合,顯然每個集合也是一個一次函數\(T_i(x)=k_i x+b_i\)

我們把這個集合分成兩種\(k_i<=0\)\(k_i>0\),顯然如果答案最後最大值的函數集合是第一種,那麽顯然肯定是在\(x=0\)取到的

所以我們單獨把\(x=0\)拎出來考慮就可以不考慮第一種函數集合的貢獻了

對於第二種\(k_i>0\)的函數集合,應該很容易發現\(max(T_i(x))\)是單調遞增的的圖像,可以二分找到答案要求的點

然後這題就做完了

對於0的處理其實就是把\(b_i\)最大且大於0的拿出來看看是否大於等於S就好了,雖然最後這樣的函數集合不一定是第一種\(k_i<=0\)但是一定考慮進去了

二分的時候也是貪心把該點的處於前\(m\)大且大於0的單個一次函數值加起來判斷一下就好了

這裏有個騷操作nth_ment(l,pos,r,cmp),表示將容器中\([l,r)\)種第pos個位置的元素變成第\(pos\)大/小(視cmp函數決定),同時pos前都是大/小於第pos大/小的元素,pos後類似

代碼

#include <cstdio>
#include <cstdlib>
#include <cctype>
#include <algorithm>
#include <cctype>
#include <iostream>
#include <queue>
#include <vector>
#define ll long long 
#define ri register int 
using std::min;
using std::max;
using std::nth_element;
inline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
template <class T>inline void read(T &x){
    x=0;int ne=0;char c;
    while(!isdigit(c=nc()))ne=c==‘-‘;
    x=c-48;
    while(isdigit(c=nc()))x=(x<<3)+(x<<1)+c-48;
    x=ne?-x:x;return ;
}
const int maxn=1000005;
const int inf=0x7fffffff;
ll v[maxn],ki[maxn],bi[maxn];
int n,m;ll s;
bool ok(int x){
    for(ri i=1;i<=n;i++)v[i]=ki[i]*x+bi[i];
    nth_element(v+1,v+m,v+n+1,std::greater<ll>());
    ll sum=0;
    if(sum>=s)return 1; 
    for(ri i=1;i<=m;i++){
        if(v[i]>0)sum+=v[i];
        if(sum>=s)return 1;
    }
    return 0;
}
int main(){
    freopen("merchant.in","r",stdin);
    freopen("merchant.out","w",stdout);
    read(n),read(m),read(s);
    for(ri i=1;i<=n;i++){
        read(ki[i]),read(bi[i]);
    }
    if(ok(0)){puts("0");exit(0);}
    int L=1,R=1e9,ans;
    while(L<=R){
        int mid=(L+R)>>1;
        if(ok(mid))ans=mid-1,R=mid-1;
        else L=mid+1;
    }
    printf("%d\n",ans+1);
    return 0;
}

[NOIP10.6模擬賽]1.merchant題解--思維+二分