首页 > 其他分享 >大鱼吃小鱼

大鱼吃小鱼

时间:2024-08-24 17:06:05浏览次数:2  
标签:10 int 重量 大鱼吃小鱼 累加 leq 权值

大鱼吃小鱼

题目描述

现在小 w 正在玩一款经典游戏——大鱼吃小鱼。

游戏规则如下:玩家操控一条初始重量为 $x$ 的鱼,它的目标是吃掉所有不超过自身当前重量的鱼。每当吃掉一条重量为 $y$ 的鱼,那么自身重量也会立即增长 $y$。

在游戏过程中,共会陆续出现 $n$ 条鱼。其中第 $i$ 条鱼重 $y_i$,其出现时间段为 $[l_i, r_i)$,即这条鱼会在时刻 $l_i$ 出现,并在时刻 $r_i$​ 前消失(包含 $l_i$ 但不包含 $r_i$​)。只有当前时刻位于 $[l_i, r_i)$ 时,小 w 才能操作自己的鱼去吃掉它。

鉴于小 w 的手速非凡,吃鱼的耗时可以忽略不计。不过最近他懒癌犯了,因此他打算只选择某一时刻进行捕食,并最大化他的鱼的重量。请计算他的鱼可能达到的最大重量。

输入描述:

第一行给出一个整数 $T(1 \leq T \leq 5 \times 10^4)$,表示数据组数。

对于每组测试数据:

第一行给出两个整数 $n, x (1 \leq n \leq 10^5, \sum{n} \leq 10^5, 1 \leq x \leq 10^9)$,表示鱼的总数与小 w 鱼的初始重量。

后面 $n$ 行,每行为三个整数 $l_i, r_i, y_i (1 \leq l_i < r_i \leq 10^9, 1 \leq y_i \leq 10^9)$。

输出描述:

一个整数,为小 w 的鱼可能达到的最大重量。

示例1

输入

2
2 17
3 4 9
9 11 8
4 1
1 2 2
2 4 1
3 5 2
4 5 3

输出

26
4

说明

第一组样例中,小 w 鱼的初始重量为 $17$,第一条鱼出现时间段为 $[3,4)$,重量 $9$;第二条鱼出现时间段为 $[9,11)$,重量 $8$ 。显然选择 $[3,4)$ 内的任意时刻进行捕食最优。

第二组样例中,小 w 鱼的初始重量为 $1$,四条鱼的出现时间段与重量依次为:时间段 $[1,2)$,重量 $2$;时间段 $[2,4)$,重量 $1$;时间段 $[3,5)$,重量 $2$;时间段 $[4,5)$,重量 $3$。显然选择 $[3,4)$ 内的任意时刻进行捕食最优。

示例2

输入

1
10 20
13 14 41
10 29 3
3 12 25
10 22 69
12 22 11
14 24 34
18 35 6
5 15 59
8 9 21
18 22 41

输出

196

 

解题思路

  对于每个区间 $(l_i, r_i, w_i)$,拆分成三元组 $(l_i, w_i, 1)$ 和 $(r_i, w_i, -1)$。对 $2n$ 个三元组按第一个元素从小到大排序,然后依次遍历用扫描线的思路对每个时刻进行处理。

  用一个集合 std::multiset 维护每个时刻有哪些鱼(权值),记当前时刻的三元组为 $(p_0, p_1, p_2)$,如果 $p_2 = 1$ 则把 $p_1$ 插入到集合中,否则 $p_2 = -1$ 则把 $p_1$ 从集合中删去。因此接下来要思考的问题是,初始的权值为 $m$,以题目的规则最终能获得多大的权值?

  暴力的做法是从小到大去累加集合中的元素,直到当前权值小于集合中最小的元素停止,时间复杂度为 $O(n^2)$。比起一个一个地去累加,不妨先在集合中二分找到比当前权值大的最小元素,记作 $x$,然后一次性把集合中小于 $x$ 的元素累加到当前权值,该过程最多执行 $O(\log{A})$ 次,$A = \max\{a_i\}$。

  如果累加了小于 $x$ 的元素后当前权值大于等于 $x$,那么下一次就会把 $x$ 累加进来,相当于让当前权值翻倍。因为所有元素最大为 $A$,因此在 $O(\log{A})$ 次操作后所有元素都会被累加。

  为了快速累加小于 $x$ 的元素,我们可以开一个权值树状数组维护集合中的元素,当然需要进行离散化。

  AC 代码如下,时间复杂度为 $O(n \log{n} \log{A})$:

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 1e5 + 5;

array<int, 3> p[N * 2];
int xs[N], sz;
LL tr[N];

int lowbit(int x) {
    return x & -x;
}

void add(int x, int c) {
    for (int i = x; i <= sz; i += lowbit(i)) {
        tr[i] += c;
    }
}

LL query(int x) {
    LL ret = 0;
    for (int i = x; i; i -= lowbit(i)) {
        ret += tr[i];
    }
    return ret;
}

int find(int x) {
    int l = 1, r = sz;
    while (l < r) {
        int mid = l + r >> 1;
        if (xs[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return l;
}

void solve() {
    int n, m;
    cin >> n >> m;
    sz = 0;
    for (int i = 0; i < n; i++) {
        int l, r, x;
        cin >> l >> r >> x;
        p[i << 1] = {l, x, 1};
        p[i << 1 | 1] = {r, x, -1};
        xs[++sz] = x;
    }
    sort(p, p + 2 * n);
    sort(xs + 1, xs + sz + 1);
    sz = unique(xs + 1, xs + sz + 1) - xs - 1;
    LL ret = m;
    memset(tr, 0, sz + 1 << 3);
    multiset<LL> st({0x3f3f3f3f3f3f3f3f});
    for (int i = 0; i < n << 1; i++) {
        int j = i;
        while (j < n << 1 && p[j][0] == p[i][0]) {
            if (p[j][2] == 1) st.insert(p[j][1]);
            else st.erase(st.find(p[j][1]));
            add(find(p[j][1]), p[j][1] * p[j][2]);
            j++;
        }
        if (*st.begin() <= m) {
            LL s = m;
            while (true) {
                auto it = st.upper_bound(s);
                s = m + query(find(*prev(it)));
                if (s < *it) break;
            }
            ret = max(ret, s);
        }
        i = j - 1;
    }
    cout << ret << '\n';
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
    
    return 0;
}

 

参考资料

  【比赛题目讲解】牛客小白月赛99:https://www.bilibili.com/video/BV182WUeuEuh/

标签:10,int,重量,大鱼吃小鱼,累加,leq,权值
From: https://www.cnblogs.com/onlyblues/p/18377940

相关文章

  • 大鱼吃小鱼
    有N 条鱼每条鱼的位置及大小均不同,他们沿着X 轴游动,有的向左,有的向右。游动的速度是一样的,两条鱼相遇大鱼会吃掉小鱼。从左到右给出每条鱼的大小和游动的方向( 0 表示向左, 1 表示向右)。问足够长的时间之后,能剩下多少条鱼?Input第 1 行: 11个数N ,表示鱼的数量(1≤N......
  • 鸿蒙开发游戏(四)---大鱼吃小鱼(互吃升级)
    鸿蒙开发游戏(一)---大鱼吃小鱼(界面部署)鸿蒙开发游戏(二)---大鱼吃小鱼(摇杆控制)鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)鸿蒙开发游戏(四)---大鱼吃小鱼(互吃升级)鸿蒙开发游戏(五)---大鱼吃小鱼(添加音效)鸿蒙开发游戏(六)---大鱼吃小鱼(称霸海洋) 前言:该篇对NPC进行了升级,这里可以投入多个......
  • 鸿蒙开发游戏(二)---大鱼吃小鱼(摇杆控制)
    鸿蒙开发游戏(一)---大鱼吃小鱼(界面部署)鸿蒙开发游戏(二)---大鱼吃小鱼(摇杆控制)鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)鸿蒙开发游戏(四)---大鱼吃小鱼(互吃升级)鸿蒙开发游戏(五)---大鱼吃小鱼(添加音效)鸿蒙开发游戏(六)---大鱼吃小鱼(称霸海洋) 前言:上一篇介绍了鸿蒙新建项目以及界面部署......
  • 鸿蒙开发游戏(一)---大鱼吃小鱼(界面部署)
    鸿蒙开发游戏(一)---大鱼吃小鱼(界面部署)鸿蒙开发游戏(二)---大鱼吃小鱼(摇杆控制)鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)鸿蒙开发游戏(四)---大鱼吃小鱼(互吃升级)鸿蒙开发游戏(五)---大鱼吃小鱼(添加音效)鸿蒙开发游戏(六)---大鱼吃小鱼(称霸海洋) 前言:你是否玩过古老而不失优雅的大鱼吃小鱼......