zoukankan      html  css  js  c++  java
  • AtCoder Beginner Contest 153 F

    题目链接 https://atcoder.jp/contests/abc153/tasks/abc153_f

    题意 : 在坐标轴上有一些怪兽,每个怪兽有对应的生命值hi,你可以对他们进行炮击,你的每次炮击可以队该点前后D范围内的怪兽造成A的伤害,问最少要炮击多少次。

    我的最初的想法是先排序,扫到最左边的怪兽,先进行炮击,把他打死,然后记录炮击了多少次,然后把其后2d距离的怪兽都炮击一下发现超时

    代码如下:

    inline ll read(){
       ll s=0,w=1;
       char ch=getchar();
       while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
       return s*w;
    }
    const int N = 2e5+5;
    struct mon
    {
            ll x,h;
    };
    mon monster[N];
    bool cmp(mon a, mon b)
    {
        return a.x < b.x;
    }
    int main()
    {
        //ios::sync_with_stdio(false);cin.tie(NULL);
        ll n, d, a;
        n = read();
        d = read();
        a = read();
        for (int i = 0; i < n; i++)
        {
            monster[i].x = read();
            monster[i].h= read();
        }
        sort(monster, monster + n,cmp);
        ll ans = 0;
        for (int i = 0; i < n; i++)
        {
            if (monster[i].h>0)
            {
                ll xx = monster[i].x + d;
                ll num = (monster[i].h + a - 1) / a;
                ans += num;
                monster[i].h = 0;
                bool flag = false;
                for (int j = i + 1; monster[j].x >= (xx - d) && monster[j].x<= xx + d && j < n;j++)
                {
                    monster[j].h-=a*num;
    
                }
            }
        }
        cout << ans << endl;
    
    }

    后来学习了大佬的代码,他是这么操作的,建立一个数组c[i],记录每个点已经炮击了几次,已经被炮击的次数我们用need来表示,那么i那个位置炮击的次数就是:c[i] += need, 下一个点 i + 1 已经炮击的次数就是c[i + 1] += c[i],因为炮击的范围是炮击点左右距离D,范围外就无效,所以每个点i你要先找到他最远能打到哪里,然后要事先减掉need,即c[j] -= need; 这样,当i到了j-1时,执行c[i+1] += c[i], need正好抵消,我觉得这个技巧太妙了

    代码里面有一个技巧可能有点难理解

    (monster[i].h - c[i]*a + a - 1)/a 这句话相当于

    ll hh = monster[i].h - c[i]*a
    if (hh % a > 0)
      need = hh/a + 1
    else if (hh %a ==0)
      need = hh/a

    代码:

    #include<iostream>
    #include<string>
    #include <cstdlib>
    #include <algorithm>
    #include<cmath>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<map>
    #include<set>
    #include<bitset>
    #include <iomanip>
    
    // #pragma comment(linker, "/STACK:1024000000,1024000000")
    // #define pi acos(-1)
    // #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    #define INF 0x7f7f7f7f //2139062143
    #define INF1 0x3f3f3f3f //1061109567
    #define INF2 2147483647
    #define llINF 9223372036854775807
    #define pi 3.141592653589793//23846264338327950254
    #define pb push_back
    #define ll long long
    #define debug cout << "debug
    ";
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    // ios::sync_with_stdio(false);cin.tie(NULL);
    #define scai(x) scanf("%d", &x)
    #define sca2i(x, y) scanf("%d %d", &x, &y)
    #define scaf(x) scanf("%lf", &x)
    #define sca2f(x, y) scanf("%lf %lf", &x, &y)
    #define For(m,n) for (int i = m;  i < n; i++)
    
    #define local
    #ifdef local
    #endif
    
    #define MAX 10233
    #define LCH(i) ((i) << 1)
    #define RCH(i) ((i) << 1 | 1)
    inline ll read(){
       ll s=0,w=1;
       char ch=getchar();
       while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
       while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
       return s*w;
    }
    const int N = 2e5+5;
    ll c[N];
    struct mon
    {
            ll x,h;
    };
    mon monster[N];
    bool cmp(mon a, mon b)
    {
        return a.x < b.x;
    }
    int main()
    {
        //ios::sync_with_stdio(false);cin.tie(NULL);
       // cout << 50ll << endl;
        ll n, d, a;
    // 这里是快读 n
    = read(); d = read(); a = read(); for (int i = 0; i < n; i++) { monster[i].x = read(); monster[i].h= read(); }
    // 对怪事的位置进行排序 sort(monster, monster
    + n,cmp); ll ans = 0; for (int i = 0,j = 0; i < n; i++) { while(j < n && monster[j].x <=monster[i].x + 2*d) // 找到这次炮击能打到的最远的怪兽 ++j; ll need = max((monster[i].h - c[i]*a + a - 1)/a, 0ll); //这个怪兽需要炮击的次数就是怪兽的生命值h减去之前炮击的次数c[i]*a,0ll的意思是longlong 的0; ans += need; c[i] += need; c[j] -= need; 把炮击范围外的第一个怪兽先剪掉need c[i+1] += c[i]; } cout << ans << endl; }

     学了差分,发现大佬的代码其实就是差分的思想。

  • 相关阅读:
    数据库底层索引
    shell脚本
    备份还原ESXi 中的虚拟机快照
    docker proxy
    yum
    ubuntu系统更换源和apt命令参数
    前端BootStrap框架和django创建项目和app
    python之路5:常用模块
    python之路3:文件操作和函数基础
    python之路4:各种器
  • 原文地址:https://www.cnblogs.com/hulian425/p/12236097.html
Copyright © 2011-2022 走看看