Atcoder Contest 153F-Silver Fox vs Monster【贪心+差分数组】 难度:***

题意:

Silver Fox is fighting with N monsters.

The monsters are standing in a row, and we can assume them to be standing on a number line. The i-th monster, standing at the coordinate Xi, has the health of Hi.

Silver Fox can use bombs to attack the monsters. Using a bomb at the coordinate x decreases the healths of all monsters between the coordinates x−D and x+D (inclusive) by A. There is no way other than bombs to decrease the monster’s health.

Silver Fox wins when all the monsters’ healths become 0 or below.

Find the minimum number of bombs needed to win.

Constraints
1≤N≤2×105
0≤D≤109
1≤A≤109
0≤Xi≤109
1≤Hi≤109
Xi are distinct.
All values in input are integers.
Input
Input is given from Standard Input in the following format:

N D A
X1 H1
:
XN HN
Output
Print the minimum number of bombs needed to win.

Sample Input 1
Copy
3 3 2
1 2
5 4
9 2
Sample Output 1
Copy
2
First, let us use a bomb at the coordinate 4 to decrease the first and second monsters’ health by 2.

Then, use a bomb at the coordinate 6 to decrease the second and third monsters’ health by 2.

Now, all the monsters’ healths are 0. We cannot make all the monsters’ health drop to 0 or below with just one bomb.

Sample Input 2
Copy
9 4 1
1 5
2 4
3 3
4 2
5 1
6 2
7 3
8 4
9 5
Sample Output 2
Copy
5
We should use five bombs at the coordinate 5.

Sample Input 3
Copy
3 0 1
300000000 1000000000
100000000 1000000000
200000000 1000000000
Sample Output 3
Copy
3000000000

题解:

用线段树就秒了 这题就不过多分析了,直接讲做法吧:首先给小怪物按坐标排序,然后准备一个差分数组来记录相邻小怪之间的hp差值。这样每遍历一个小怪时,因为炸弹的杀伤是一样的,所以这个小怪物身边的其他怪物和它的hp差其实是保持不变的。但是炸弹范围不是无限,所以在差分数组中第一个不会被炸弹炸到的小怪加上这次炸弹的杀伤,意思就是表明:这个安全的小怪物和前面那个被炸的小怪物之间的hp差值改变了了,相当于时时维护这个差分数组。这样遍历完的时间复杂度是O(n)。

一般同学(包括我)开始做的时候都是排好序然后遍历能被炸到的小怪物,这样时间复杂度是O(n2),是不可取的。

代码:

#include<stdio.h>
#include<stdlib.h>
struct crystal
{
	long long x;
	long long h;
	long long t;
}mon[200005];
int inc(const void *a, const void *b)
{
    struct crystal m = *(struct crystal *)a;
    struct crystal n = *(struct crystal *)b;
    if(m.x<n.x)return -1;
    else return 1;
}
int erfen(long long x,int n)
{
    int l=0,r=n,mid=(r+l)/2;
    while(l<r)
    {
        mid=(r+l)/2;
        if(mon[mid].x>x)r=mid;
        else l=mid;
        if(r==l+1)return l;
    }
    return -1;
}
int main()
{
    int n,a;
	long long d,sum=0,kill;
    scanf("%d%lld%d",&n,&d,&a);
    for(int i=0;i<n;i++)scanf("%lld%lld",&mon[i].x,&mon[i].h);
    qsort(mon,n,sizeof(struct crystal),inc);
    mon[0].t=mon[0].h;
    for(int i=1;i<n;i++)mon[i].t=mon[i].h-mon[i-1].h;
    int l,r;
    for(int i=0;i<n;i++)
    {
    	if(mon[i].t<=0)mon[i+1].t+=mon[i].t;
    	else
        {
            l=i;
            r=erfen(mon[i].x+2*d,n)+1;
            if(mon[l].t%a==0)kill=mon[l].t/a;
            else kill=mon[l].t/a+1;
            sum+=kill;
            mon[r].t+=kill*a;
            mon[l].t-=kill*a;
            mon[i+1].t+=mon[i].t;
        }
	}
    printf("%lld\n",sum);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值