[一本通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;
}
相关文章
相关标签/搜索