• luogu P2107 小Z的AK计划


    最近复习了一下堆,于是去luogu上找一些简单题写一写

    贪心的想,小z不会到一半以后回头去Ak,因为这样从时间上想肯定是不优的,他可以早在之间经过时就AK
    所以我们可以将所有机房按照横坐标排序
    可以想到的是,我们最后肯定是要走过所有的机房,也就是说路程消耗的疲劳值是不可避免的。
    我们只能尽可能的减少小ZAK所花费的时间
    贪心的考虑,当我们在机房Ak所花费的时间长时,我们可能能在这个时间内AK更多的机房
    所以当时间出问题时,我们肯定要取出堆顶删除以便AK更多的机房。
    我们维护一个关于机房AK时间的大根堆,每次先假定要Ak,然后将时间丢入堆中,所到当前机房所花费的时间比总时间大,则移除堆顶
    但是需要注意的是,移除堆顶时,我们的答案并不需要减少,因为刚刚插入一个,然后超过了总时间,在移除一个,刚刚好抵消
    至于为什么只需要移除堆顶:
    我在题解上看到过用while循环去移除堆顶的,然而实际并不需要,因为我们刚刚插入一个新元素
    对于这个元素来说,若他不是堆中最大元素,显然我们移除最大的肯定就把这个新元素占的地方给腾出来了
    若是最大元素,那么直接删除就等于过而不入,对答案没有影响

    这样我们就能AC这道题

    嗯好吧,其实思路是有些问题的

    因为是这样的,可能的是,我们在当前这个机房,即使过而不入,单单是走过去,在加上之前的选择并AK机房耗费的时间就把总时间给超了

    这样我们不得不多次弹出堆顶,同时在弹出第一个堆顶后,剩下的弹出多少个,答案数就要减去多少

    好在这题没有卡

    不会且没看stl的我选择手写二叉堆

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define uint unsigned int
     4 #define ull unsigned long long
     5 using namespace std;
     6 const int maxn = 110000;
     7 struct shiki {
     8     ll x, t;
     9 }a[maxn];
    10 ll heap[maxn << 1], tot = 0, num = 0;
    11 ll n, m, top = 0;
    12 ll ans = 0; 
    13 
    14 inline ll read() {
    15     ll x = 0, y = 1;
    16     char ch = getchar();
    17     while(!isdigit(ch)) {
    18         if(ch == '-') y = -1;
    19         ch = getchar();
    20     }
    21     while(isdigit(ch)) {
    22         x = (x << 1) + (x << 3) + ch - '0';
    23         ch = getchar();
    24     }
    25     return x * y;
    26 }
    27 
    28 inline void up(int p) {
    29     while(p > 1) {
    30         if(heap[p] > heap[p / 2]) {
    31             swap(heap[p], heap[p / 2]);
    32             p /= 2;
    33         }
    34         else break;
    35     }
    36 }
    37 
    38 inline void down(int p) {
    39     int s = p * 2;
    40     while(s <= tot) {
    41         if(s < tot && heap[s] < heap[s + 1]) s++;
    42         if(heap[p] < heap[s]) {
    43             swap(heap[s], heap[p]);
    44             p = s, s = p >> 1;
    45         }
    46         else break;
    47     }
    48 }
    49 
    50 inline void extract() {
    51     heap[1] = heap[tot--];
    52     down(1);
    53 }
    54 
    55 inline void insert(ll k) {
    56     heap[++tot] = k;
    57     up(tot);
    58 }
    59 
    60 inline bool cmp(shiki a, shiki b) {
    61 return a.x < b.x;}
    62 
    63 inline int get_top(){return heap[1];}
    64 
    65 int main() {
    66     n = read(), m = read();
    67     for(int i = 1; i <= n; ++i) {
    68         ll x = read(), t = read();
    69         if(x <= m && t <= m) {
    70             a[++top].x = x;
    71             a[top].t = t;
    72         }
    73     }
    74     sort(a + 1, a + top + 1, cmp);
    75     for(int i = 1; i <= top; ++i) {
    76         insert(a[i].t);
    77         num += (a[i].x - a[i - 1].x) + a[i].t;
    78         if(num <= m) ans++;
    79         if(num > m) {
    80             num -= get_top();
    81             extract();
    82         }
    83     }
    84     printf("%lld
    ", ans);
    85     return 0;
    86 } 
  • 相关阅读:
    脚本——猜拳
    脚本——基础命令
    脚本——1-100奇数的和
    脚本——判断文件类型
    脚本——判断分数是否合格
    脚本——判断服务是否开启
    脚本——ping一个网址三次
    脚本——判断是否root用户
    脚本——查看目录是否存在
    第十八天:CSV、JSON、Excel、SQLite
  • 原文地址:https://www.cnblogs.com/ywjblog/p/9858084.html
Copyright © 2020-2023  润新知