[一本通1676]手機遊戲 題解

1676:手機遊戲



題目描述

明明的手機上有這樣一個遊戲,一排$n$個怪物,每一個怪物的血量是$m_i$。如今明明能夠射出$k$個傷害均爲$p$的火球,當某個火球射到第$i$個怪物,除了這個怪物會掉血$p$之外,它左邊的第$j$個怪物($j≤i$),也會遭到$max(0,p-(i-j)^2)$的濺射傷害。當某個怪物的血量爲負的時候,它就死了,但它的屍體依然存在,即其餘怪物不會由於它死而改變位置。ios

明明想用這$k$個火球消滅掉全部的怪物,但他同時但願每一個火球的傷害$p$能儘量的小,這樣他才能完美過關。優化

全部數均爲整數。spa

輸入

第一行兩個數$n,k$。code

第二行$n$個數$m_1,m_2,…,m_n$表示每一個怪物的生命值。blog

輸出

一行一個整數表示最小的符合要求的$p$值。遊戲

輸入樣例

3 1
1 4 5

輸出樣例

6

提示

數據規模

對於30%的數據,$n≤500$。string

對於100%的數據,$1≤n≤50000,1≤k≤100000,1≤m_i≤10^9$。io

思路

很簡單的一道常規二分,雖然有優化方,但我不用
注意要開long long
imagetable

代碼

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

typedef long long ll;

const int N = 5e4 + 12;

int num[N];

ll offset[N]; //怪物受到的傷害

int n, k;

inline bool check(ll p)
{
    int cnt = 0;
    memset(offset, 0, sizeof(offset));
    for (int i = n; i >= 1; i--)
    {
        while (offset[i] <= num[i])
        {
            offset[i] += p;
            cnt++;
            if (cnt > k)
                return false;
            for (ll j = 1; p - j * j > 0 && i - j >= 1; j++)
            {
                offset[i - j] += p - j * j;
            }
        }
    }
    return true;
}

int main()
{
    scanf(" %d %d", &n, &k);
    for (int i = 1; i <= n; i++)
        scanf(" %d", &num[i]);
    ll l = 1, r = 1e18;

    while (l < r)
    {
        ll mid = l + r >> 1;
        if (check(mid))
            r = mid;
        else
            l = mid + 1;
    }
    printf("%d", r);
    return 0;
}
相關文章
相關標籤/搜索