HDU 4970-Killing Monsters

Killing Monsters

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 2756    Accepted Submission(s): 1033


题目链接:点击打开链接



Problem Description
Kingdom Rush is a popular TD game, in which you should build some towers to protect your kingdom from monsters. And now another wave of monsters is coming and you need again to know whether you can get through it.

The path of monsters is a straight line, and there are N blocks on it (numbered from 1 to N continuously). Before enemies come, you have M towers built. Each tower has an attack range [L, R], meaning that it can attack all enemies in every block i, where L<=i<=R. Once a monster steps into block i, every tower whose attack range include block i will attack the monster once and only once. For example, a tower with attack range [1, 3] will attack a monster three times if the monster is alive, one in block 1, another in block 2 and the last in block 3.

A witch helps your enemies and makes every monster has its own place of appearance (the ith monster appears at block Xi). All monsters go straightly to block N.

Now that you know each monster has HP Hi and each tower has a value of attack Di, one attack will cause Di damage (decrease HP by Di). If the HP of a monster is decreased to 0 or below 0, it will die and disappear.
Your task is to calculate the number of monsters surviving from your towers so as to make a plan B.
 

Input
The input contains multiple test cases.

The first line of each case is an integer N (0 < N <= 100000), the number of blocks in the path. The second line is an integer M (0 < M <= 100000), the number of towers you have. The next M lines each contain three numbers, Li, Ri, Di (1 <= Li <= Ri <= N, 0 < Di <= 1000), indicating the attack range [L, R] and the value of attack D of the ith tower. The next line is an integer K (0 < K <= 100000), the number of coming monsters. The following K lines each contain two integers Hi and Xi (0 < Hi <= 10^18, 1 <= Xi <= N) indicating the ith monster’s live point and the number of the block where the ith monster appears.

The input is terminated by N = 0.
 

Output
Output one line containing the number of surviving monsters.

Sample Input
5
2
1 3 1
5 5 2
5
1 3
3 1
5 2
7 3
9 1
0
 


Sample Output
3


Hint
In the sample, three monsters with origin HP 5, 7 and 9 will survive.




题意:
王国Rush是一种流行的TD游戏,在游戏中你应该建造一些塔来保护你的王国免受怪物的伤害。现在又有一波怪物来了,你需要知道你是否能打死它。假设街道是分块的,有N个块(连续编号从1到N)。怪物的路径是一条直线(在它所在的位置只能向前走),在敌人到来之前,你已经建造了M个塔。每座塔都有一个攻击范围[L,R],意思是它可以攻击该范围的所有敌人,其中L <= R。一旦一个怪物进入街道,每一个攻击范围包括该街道的塔,都会攻击怪物一次。
例如,一个带有攻击范围的塔(1,3)将会攻击一个怪物3次,如果怪物还活着,第一次攻击在第1块,第二次攻击在第2块,最后一次攻击在第3块。
女巫帮助你的敌人,让每一个怪物都有自己的地方出现(第i个怪物出现在块Xi)。所有怪物可以前进到N(如果它还活着就前进一格) .现在你知道每个怪物都有耐攻击值Hi,每个塔都有攻击值Di,一个攻击将导致怪物减少Di点伤害
如果一个怪物的耐攻击值降低到0或小于0,它就会死亡并消失。
你的任务是计算从你的塔中存活的怪物数量。


分析:
树状数组的思想,不过现在没认真去研究过它,本题用了一个很巧妙的办法(注意本题的数据范围)




#include <iostream>
#include<stdio.h>
#include<string.h>
#include<string>
#include<math.h>
using namespace std;
long long int s[100005];
int main()
{
    int sum,n,m,k,a,b,c,ans;
    long long int q;
    while(scanf("%d",&n),n)
    {
        memset(s,0,sizeof(s));
        ///这里得注意,虽然定义的是全局变量但也得初始化,在这里wa了一次
        scanf("%d",&m);
        sum=0;///是用来做中间变量存储的,其实没有也行
        ans=0;///统计存活的怪物的数量
        for(int i=1;i<=m;i++)
        {
            scanf("%d %d %d",&a,&b,&c);
            s[a]+=c;///将区间的左边界加上攻击值
            s[b+1]-=c;
            /**出右边界就减去该攻击值,因为该攻击值只在给定的区间起作用,但会有宝宝不明白为什么
            不是将该区间的所有包含值都加上,而是只单单加上左边界,下面就会介绍**/
        }
        for(int i=1;i<=n;i++)///更新区间,区间中每个元素所拥有的攻击值都会在这里进行总结更新
        {
            sum+=s[i];
            /**sum是用来保存一路下来某个元素所应得得攻击值,在这里就可以看到sum的作用以及为什么
            上面的存储方式了,在左边界加上的值在给定的区间都会加一遍,超出右边界的时候就减去该值,
            往后都不会有该区间的值,是不是很巧妙**/
            s[i]=sum;///i点所拥有的攻击值
        }
        for(int i=n-1;i>=1;i--)
        /**这里反向累加一遍,是为了后面方便判断,每个点的攻击值都更新为从该点到N
        的所有攻击值的累加情况,你想啊,怪物可以向前移动,在没死的情况下可以一直移动到
        N,而在移动的过程中,如果某个塔的攻击范围包括该点,是不是它就会减少对饮的耐攻击值,
        所以我们这样一累加,后面给出怪物的耐攻击和所在点的话,就可以直接判断该点所存储的攻击值
        是否能将它杀死,如果不能,说明它可以活到最后**/
            s[i]+=s[i+1];
        scanf("%d",&k);
        for(int i=0;i<k;i++)
        {
            scanf("%lld %d",&q,&b);
            if(q>s[b])
                ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}










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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值