hdu 4970 Killing Monsters 【树状数组(区间修改,点查询)】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4970


题目大意:

类似于一类塔防游戏。monster只能在一条长为N的直线上移动,有m个塔,每个塔有自己的防守范围以及在范围内每个点的伤害值;有k个monster,每个monster有自己的HP,以及刚开始出现在直线上的位置。问最后有多少monster能活着。


此题就是很裸的区间修改,区间查询问题。

和上次多校赛的塔防那题差了很多,属于签到题范围。

有两种方法,一种是利用树状数组的区间修改,点查询的方法做,维护一个数组attack[i]代表从i到n会受到的总伤害。复杂度为O(n*logn);

第二种方法是建立一个temp数组。对于每个塔的属性(l,r,a)(范围为[l,r],伤害为a),使temp[l]=a,temp[r+1]=-a;扫完所有塔之后,求其前缀和数组,这个前缀和数组中每一个元素就代表怪物在当前点会受到的伤害,再从后面往前面扫一遍,即可得到方法一中的attack数组。复杂度为O(n)。

最后计算有多少个monster的HP能大于他走到最后受到的总伤害,即可得到答案。


方法一的代码如下:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#define N 100100
using namespace std;
long long c[N];
long long sum[N];
long long n;
long long getnum(long long x)
{
    long long rnt=0;
    for(long long i=x;i<=n;i+=(i&(-i)))
    {
        rnt+=c[i];
    }
    return rnt;
}
void add(long long i,long long a)
{
    while(i>=1)
    {
        c[i]+=a;
        i-=(i&(-i));
    }
}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("D:/in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(~scanf("%I64d",&n)&&n)
    {
        long long m;
        memset(c,0,sizeof(c));
        //memset(sum,0,sizeof(sum));
        scanf("%I64d",&m);
        while(m--)
        {
            long long l,r,a;
            scanf("%I64d%I64d%I64d",&l,&r,&a);
            add(r,a),add(l-1,-a);
        }
        sum[n+1]=0;
        for(long long i=n;i>=1;i--)
        {
            sum[i]=sum[i+1]+getnum(i);
        }
        long long K;
        scanf("%I64d",&K);
        long long ans=0;
        while(K--)
        {
            long long h,x;
            scanf("%I64d%I64d",&h,&x);
            if(h>=sum[x]) ans++;
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

第二种方法是题解的方法,大家可以自己试着写一下~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值