Atcoder F - Silver Fox vs Monster(贪心 + 差分)

题意
银狐在和怪物搏斗,怪物们站成一排,我们可以假设它们站在数轴上。第i个怪物,站在坐标 X i X_i 处,健康度为 H H 。银狐可以用炸弹攻击怪物。在坐标x处使用炸弹会降低所有怪物在坐标 x D x-D x + D x + D (包括端点)之间的生命值。除了用炸弹降低怪物的生命值外,没有其他方法。当所有怪物的治疗为0或以下时,银狐获胜。找出获胜所需的最低炸弹数量。
思路:
贪心
按怪物出现的坐标从小到大排好序,然后每次贪心的选取第 i i 个怪物右侧距离为 D D 处设置炸弹。这样是显然正确的。然后可以记录一下右侧 x i + 2 D x_i+2D 处位置,如果后面的怪物的 x x < = x i + 2 D <=x_i+2D ,那么相应的生命值就减去相应的伤害。
可是如果双重循环查找会超时,那可怎么办呢?
差分
设置一个差分数组 q [   ] q[ \ ] ,每次我们贪心的选取完炸弹坐标后,可以二分查找 < = x i + 2 D <=x_i+2D 范围内最远点进行差分。
A C   C o d e AC \ Code

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define ll long long
const ll N = 2e5+10 ;
struct node{
   ll a,b;
}res[N];
bool cmp(node A,node B){
   return A.a < B.a;
}
ll q[N];
int main(){
   ios::sync_with_stdio(false); cin.tie(0);
   ll n,d,x;
   cin >> n >> d >> x;
   d <<= 1;
   for(ll i = 1;i <= n; ++i){
      cin >> res[i].a >> res[i].b;
   }
   sort(res + 1,res + n + 1,cmp);
   ll sum = 0;
   for(ll i = 1;i <= n;++ i){
      q[i] += q[i-1];
      res[i].b -= q[i] * x;
      if(res[i].b <= 0) continue;
      ll p = (res[i].b + x - 1) / x;
      sum += p;
      q[i] += p;
      ll l = i,r = n;
      ll temp = res[i].a + d;
      while(l < r){
         ll mid = l + r + 1>> 1;
         if(res[mid].a <= temp) l = mid;
         else r = mid - 1;
      }
      q[l + 1] -= p;
   }
   cout<<sum;
   
 
 
}
发布了632 篇原创文章 · 获赞 27 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_43408238/article/details/104091515
Fox