Plants vs. Zombies【二分答案】

題目鏈接


  題意:有N盆花,現在有一個澆花機器人,當它走到一個花盆面前的時候,可以給該花澆對應的a[i]的權值的防禦值(植物大戰殭屍嘛),然後呢,機器人一共可以走M步,問最後防禦權值最小的花的最大權是多少,最小值最大問題。(機器人一開始處於位置0,花是1~N)

  首先,二分答案是比較好想到的,就是check的時候,條件是真的多,譬如說,我們走到一個花,它還需要澆水,那麼可以i、i+1、i、i+1、……這樣來回的走,但是如果最後一個花,花N的時候,那麼就有可能它不需要澆了,這裏需要判斷一下,再者,如果是中間步驟的時候,步數超過M了,需要立馬判斷掉。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 1e5 + 7;
int N;
ll M, a[maxN], t[maxN];
bool check(ll lim)
{
    for(int i=1; i<=N; i++)
    {
        t[i] = (lim + a[i] - 1LL) / a[i];
        if(t[i] >= M) return false;
    }
    ll step = 0;
    for(int i=1; i<=N; i++)
    {
        if(i == N && t[N] <= 0) return true;
        step++; t[i]--;
        if(step > M) return false;
        if(t[i] <= 0) continue;
        step += t[i] * 2LL;
        if(step > M) return false;
        t[i + 1] -= t[i];
    }
    return true;
}
int main()
{
    int T; scanf("%d", &T);
    while(T--)
    {
        scanf("%d%lld", &N, &M);
        for(int i=1; i<=N; i++) scanf("%lld", &a[i]);
        ll l = 1, r = 1e17 + 10, mid = 0, ans = 0;
        while(l <= r)
        {
            mid = (l + r) / 2LL;
//            mid = 4;
            if(check(mid))
            {
                l = mid + 1;
                ans = mid;
            }
            else r = mid - 1;
        }
        printf("%lld\n", ans);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章