Monsters And Spells(1700)区间合并,贪心 Educational Codeforces Round 121 (Rated for Div. 2)

C. Monsters And Spells
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Monocarp is playing a computer game once again. He is a wizard apprentice, who only knows a single spell. Luckily, this spell can damage the monsters.

The level he’s currently on contains 𝑛 monsters. The 𝑖-th of them appears 𝑘𝑖 seconds after the start of the level and has ℎ𝑖 health points. As an additional constraint, ℎ𝑖≤𝑘𝑖 for all 1≤𝑖≤𝑛. All 𝑘𝑖 are different.

Monocarp can cast the spell at moments which are positive integer amounts of second after the start of the level: 1,2,3,… The damage of the spell is calculated as follows. If he didn’t cast the spell at the previous second, the damage is 1. Otherwise, let the damage at the previous second be 𝑥. Then he can choose the damage to be either 𝑥+1 or 1. A spell uses mana: casting a spell with damage 𝑥 uses 𝑥 mana. Mana doesn’t regenerate.

To kill the 𝑖-th monster, Monocarp has to cast a spell with damage at least ℎ𝑖 at the exact moment the monster appears, which is 𝑘𝑖.

Note that Monocarp can cast the spell even when there is no monster at the current second.

The mana amount required to cast the spells is the sum of mana usages for all cast spells. Calculate the least amount of mana required for Monocarp to kill all monsters.

It can be shown that it’s always possible to kill all monsters under the constraints of the problem.

Input
The first line contains a single integer 𝑡 (1≤𝑡≤104) — the number of testcases.

The first line of the testcase contains a single integer 𝑛 (1≤𝑛≤100) — the number of monsters in the level.

The second line of the testcase contains 𝑛 integers 𝑘1<𝑘2<⋯<𝑘𝑛 (1≤𝑘𝑖≤109) — the number of second from the start the 𝑖-th monster appears at. All 𝑘𝑖 are different, 𝑘𝑖 are provided in the increasing order.

The third line of the testcase contains 𝑛 integers ℎ1,ℎ2,…,ℎ𝑛 (1≤ℎ𝑖≤𝑘𝑖≤109) — the health of the 𝑖-th monster.

The sum of 𝑛 over all testcases doesn’t exceed 104.

Output
For each testcase, print a single integer — the least amount of mana required for Monocarp to kill all monsters.

Example
inputCopy
3
1
6
4
2
4 5
2 2
3
5 7 9
2 1 2
outputCopy
10
6
7
Note
In the first testcase of the example, Monocarp can cast spells 3,4,5 and 6 seconds from the start with damages 1,2,3 and 4, respectively. The damage dealt at 6 seconds is 4, which is indeed greater than or equal to the health of the monster that appears.

In the second testcase of the example, Monocarp can cast spells 3,4 and 5 seconds from the start with damages 1,2 and 3, respectively.

In the third testcase of the example, Monocarp can cast spells 4,5,7,8 and 9 seconds from the start with damages 1,2,1,1 and 2, respectively.

题意 :

  • 有n个怪,给出分别出现的时间time和被打败至少需要的力量power,已知攻击可以是突变为0或者1,也可以从1开始每次连续加一,要求打败所有怪物,求最小的攻击之和

思路 :

  • 对于每个怪,我们都可以得出一个最晚开始时间 t i m e [ i ] − p o w e r [ i ] + 1 time[i]-power[i]+1 time[i]power[i]+1,且攻击至少持续到它当前这个时刻;因此,转化为一个区间合并问题,结果就是合并后的所有区间的长度和
  • 鬼畜之处在于累加区间和的公式会溢出然后wa,以后涉及ll的公式中,数字最好还是写成LL的形式
#include <iostream>
#include <vector>
#include <algorithm>
#define endl '\n'
using namespace std;

typedef long long ll;
typedef pair<long, long> PLL;
const int N = 110;

int n;
ll appear[N], power[N];

void solve()
{
    cin >> n;
    for (int i = 1; i <= n && cin >> appear[i]; i ++ );
    for (int i = 1; i <= n && cin >> power[i]; i ++ );
    
    vector<PLL> ve;
    for (int i = 1; i <= n; i ++ ) ve.push_back({appear[i] - power[i] + 1, appear[i]});
    sort(ve.begin(), ve.end());
    
    vector<PLL> res;
    ll st = -2e9, ed = -2e9;
    for (int i = 0; i < ve.size(); i ++ )
    {
        ll x = ve[i].first, y = ve[i].second;
        if (i == 0) st = x, ed = y;
        else
        {
            if (x > ed)
            {
                res.push_back({st, ed});
                st = x, ed = y;
            }
            else if (y > ed) ed = y;
        }
    }
    if (st != -2e9 && ed != -2e9) res.push_back({st, ed});
    
    ll ans = 0;
    for (auto it : res)
    {
        ll x = it.first, y = it.second;
        ans += (it.second - it.first + 2LL) * (it.second - it.first + 1LL) / 2;
    }
    cout << ans << endl;
}

int main()
{
    ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    
    int _; cin >> _;
    while (_ -- )
        solve();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值