Educational Codeforces Round 121 (Rated for Div. 2) C. Monsters And Spells

翻译:

Monocarp又在玩电脑游戏了。他是个巫师学徒,只会一个咒语。幸运的是,这个法术可以伤害怪物。

他目前所在的关卡包含𝑛个怪物。他们中的𝑖-th在关卡开始后𝑘𝑖秒出现,并拥有ℎ𝑖生命值。作为附加约束,对于所有1≤𝑖≤𝑛,ℎ𝑖≤𝑘𝑖。所有𝑘𝑖都是不同的。

Monocarp可以在关卡开始后的正整数秒数的时刻施放法术:1、2、3、…如果他在前一秒没有施法,伤害为1。否则,让前一秒的伤害为𝑥。然后他可以选择伤害为𝑥+1或1。法术使用法力值:施放伤害为𝑥的法术使用𝑥法力值。法力值不会回复。

要杀死𝑖-th怪物,Monocarp必须在怪物出现的确切时刻施放至少ℎ𝑖的伤害法术,即𝑘𝑖。

注意,即使当前秒内没有怪物,单果也可以施放该法术。

施法所需的法力值是所有施法法术的法力值之和。计算Monocarp杀死所有怪物所需的最小法力值。

我们可以看到,在问题的限制条件下,玩家总是有可能杀死所有怪物。

输入
第一行包含一个整数𝑡(1≤𝑡≤104)——测试用例的数量。

测试用例的第一行包含一个整数𝑛(1≤𝑛≤100)——关卡中的怪物数量。

测试用例的第二行包含𝑛整数𝑘1<𝑘2<⋯<𝑘𝑛(1≤𝑘𝑖≤109)-从开始𝑖-th怪物出现的秒数。所有𝑘𝑖都是不同的,𝑘𝑖是按递增顺序提供的。

测试用例的第三行包含𝑛整数ℎ1,ℎ2,…,ℎ𝑛(1≤ℎ𝑖≤𝑘𝑖≤109)-𝑖-th怪物的生命值。

所有测试用例中𝑛的总和不超过104。

输出
对于每个测试用例,打印一个整数- Monocarp杀死所有怪物所需的最小法力值。

例子
inputCopy
3.
1
6
4
2
4个5
2 - 2
3.
5 7 9
2 1 2
outputCopy
10
6
7
请注意
在这个例子的第一个测试案例中,Monocarp可以在开始后3、4、5和6秒施放伤害分别为1、2、3和4的法术。6秒时造成的伤害为4,这确实大于或等于出现的怪物的生命值。

在这个例子的第二个测试用例中,Monocarp可以在开始时施放3、4和5秒的法术,伤害分别为1、2和3。

在这个例子的第三个测试案例中,Monocarp可以在开始时施放4,5,7,8,9秒的法术,伤害分别为1,2,1,1和2。

思路:

刚开始看到题,第一感觉是,只需要判断,中间区间能不能到达怪物的血量,后来想一下,如果后一个能到达,但是后后面的根据前一个不能到达该怎么办,那么不能到达的前边就不能再从1开始加,就需要从前的来继承。n只有100个,感觉可以暴力,每次也就往后暴力100个,如果当前减少,从当前的值开始加遍历后边的如果有不能到达,那就再退后前一个值,来累加,每次这样。最后肯定是能全部到达的,但是感觉太麻烦了(本人太懒了~~~,想了想有没有什么智慧方法,思维题的应该有更巧妙的做法,而不是 暴力(主要我太菜了,刚开始就想到了暴力,后来发现从后面来更新怪物要求血量,这样就可以保证每次可以到达,如果后一个减去中间区间大于当前值,那么如果取当前值肯定满足不了,那么我们就可以更新它,然后倒着来遍历一遍,我们在进行模拟即可。

代码:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long  ll;
int n,t;
inline __int128 read(){
    __int128 x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if(ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x * f;
}
inline void print(__int128 x){
    if(x < 0){
        putchar('-');
        x = -x;
    }
    if(x > 9)
        print(x / 10);
    putchar(x % 10 + '0');
}

struct we{
    ll x,y;
}c[105];
void solv(){
    cin>>n;
    for (int i=1; i<=n; i++) {
        cin>>c[i].x;
    }
    for (int i=1; i<=n; i++) {
        cin>>c[i].y;
    }
    for (int i=n-1; i>=1; i--) {
        c[i].y=max(c[i].y,c[i+1].y-(c[i+1].x-c[i].x));
    }
    ll an=0;
    for (int i =1; i<=n; i++) {
        if (i==1) {
            an=(c[i].y+1)*c[i].y/2;
            continue;
        }
        if ((c[i].x-c[i-1].x)>=c[i].y) {
            an+=(c[i].y+1)*c[i].y/2;
        }
        else{
            an+=(c[i-1].y+c[i].x-c[i-1].x+c[i-1].y+1)*(c[i].x-c[i-1].x)/2;
            c[i].y=c[i-1].y+c[i].x-c[i-1].x;
        }
    }
    printf("%lld\n",an);
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(); cout.tie();
    cin>>t;
    while (t--) {
        solv();
    }
    return 0;
}
 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值