Solution of 牛客集训提高组第三场2023B 摆渡车

摆渡车

https://ac.nowcoder.com/acm/contest/65194/B

  • 个乘客要依次经过检票口等待摆渡车,其中第 个人的重量为 ,摆渡车载重为

  • 当乘客 通过检票口时摆渡车来了则他能优先登上摆渡车。

  • 剩下的 则尽可能多上人到摆渡车上。

  • 对于每个 求如果在 通过检票口时摆渡车来了,会有多少人过了检票口上不了车。

首先,尽可能多上车就是指先让轻的人上,贪心易证。

此时,问题转换成在 种选择尽可能多的轻的人使得其重量不超过

假设 排好了序,则求的是

看着是不是很眼熟?

没错,权值线段树来了。

但是看数据范围:

如果直接权值线段树就 了。

但是有个东西叫离散化啊。

话说回来,具体怎么实现呢?

  1. 离散化

  2. 线段树维护该区间内元素的数量及和

  3. 建树就是普通线段树建树

  4. 更新就是单点更新,查找到该点后直接更新元素的数量与和

  5. 查找时,如果是叶子节点,就做除法,看还能塞几个人进去,注意判除零;如果不是,就看上限有没有超过左子树元素的个数,超过了就进入右子树,否则进入左子树,不要忘了把上限减去左子树的和并把答案加上左子树的元素个数

这样就是 的了,但是常数偏大,可以过,我的代码跑了 ,据说还有大佬用树状数组做的,本蒟蒻不会。

/*
思想:权值线段树+离散化
*/

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

constexpr int MAXN = 1e5+5;

struct Node {
    int l, r, cnt;
    long long sum;
} tr[MAXN * 4];
map<int, int> c;

void pushup(int k) {
    tr[k].cnt = tr[k << 1].cnt + tr[k << 1 | 1].cnt;
    tr[k].sum = tr[k << 1].sum + tr[k << 1 | 1].sum;
}

void build(int k, int l, int r) {
    tr[k] = {l, r, 0, 0};
    if (l == r) return;
    int md = l + r >> 1;
    build(k << 1, l, md);
    build(k << 1 | 1, md + 1, r);
}

void update(int k, int x, int y) {
    if (tr[k].l == tr[k].r) {
        tr[k].cnt++;
        tr[k].sum += y;
        return;
    }
    int md = tr[k].l + tr[k].r >> 1;
    if (x <= md) update(k << 1, x, y);
    else update(k << 1 | 1, x, y);
    pushup(k);
}

int query(int k, long long m) {
    if (tr[k].l == tr[k].r) {
        if (tr[k].sum == 0) return 0;
        return m / (tr[k].sum / tr[k].cnt);
    }
    if (tr[k << 1].sum >= m) {
        return query(k << 1, m);
    } else {
        return query(k << 1 | 1, m - tr[k << 1].sum) + tr[k << 1].cnt;
    }
}

int w[MAXN];

void work() {
    c.clear();
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
        c[w[i]] = 0;
    }
    int cnt = 0;
    for (auto &i : c) {
        i.second = ++cnt;
    }
    build(1, 1, cnt);
    for (int i = 1; i <= n; i++) {
        // for (int j = 1; j <= 5; j++)
        //     cerr << tr[j].l << " " << tr[j].r << " " << tr[j].cnt << " " << tr[j].sum << endl;
        // cerr << endl;
        cout << i - query(1, m - w[i]) - 1 << " ";
        update(1, c[w[i]], w[i]);
    }
    cout << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int T;
    cin >> T;
    while (T--) {
        work();
    }

    return 0;
}
全部评论
%%%%%%%%%%%%%%%%%%%%%%%%%%%%555
点赞 回复 分享
发布于 2023-10-10 15:50 江西

相关推荐

咦哟,从去年八月份开始长跑,两处实习转正都失败了,风雨飘摇,终于拿到offer了更新一下面试记录:秋招:多部门反复面试然后挂掉然后复活,具体问了啥已经忘了,只是被反复煎炸,直至焦香😋春招:base北京抖音hr打来电话说再次复活,准备面试,gogogo北京抖音一面:六道笔试题:1.promise顺序2.定义域问题3.flat展开4.并发请求5.岛屿数量算法(力扣)深度,广度都写6.忘记了,好像也是算法,难度中等其他问题多是框架底层设计,实习项目重难点~~~秒过😇北京抖音二面:三道笔试题:(为什么只有三道是因为第三道没做出来,卡住了)1.中等难度算法(忘记啥题了,应该是个数组的)2.认识js的继承本质(手写继承模式,深入js的面相对象开发)3.手写vue的响应式(卡在了watch,导致挂掉)---后知后觉是我的注册副作用函数写得有问题,有点紧张了其他题目多是项目拷打,项目亮点,对实习项目的贡献~~~第二天,挂,but立马复活转战深圳客服当天约面深圳客服一面:六道笔试题,由于面过太多次字节,面试官叫我直接写,不用讲,快些写完😋,具体都是些继承,深拷贝(注意对数组对象分开处理,深层次对象,循环引用),加中等难度算法题~~~秒过深圳客服二面:口诉八股大战:大概囊括网络,浏览器渲染原理,动画优化,时间循环,任务队列等等(你能想到的简单八股通通拉出来鞭尸😋)算法题:笔试题6道:1:找出数组内重复的数,arr[0]-arr[n]内的数大小为[1-n],例如[1,2,2,3,3]返回[2,3],要求o(n),且不使用任何额外空间(做到了o(n),空间方面欠佳,给面试官说进入下一题,做不来了)2:原滋原味的继承(所以继承真滴很重要)3:力扣股票购买时机难度中等其他滴也忘记了,因为拿到offer后鼠鼠一下子就落地了,脑子自动过滤掉可能会攻击鼠鼠的记忆😷~~~秒过深圳客服三面:项目大战参与战斗的人员有:成员1:表单封装及其底层原理,使用成本的优化,声明式表单成员2:公司内部库生命周期管理成员3:第三方库和内部库冲突如何源码断点调试并打补丁解决成员4:埋点的艺术成员5:线上项目捷报频传如何查出内鬼成员6:大文件分片的风流趣事成员7:设计模式对对碰成员8:我构建hooks应对经理的新增的小需求的故事可能项目回答的比较流利,笔试题3道,都很简单,相信大家应该都可以手拿把掐😇~~~过过过无hr面后续煎熬等待几天直接hr打电话发offer了,希望大家也可以拿到自己心仪的offer
法力无边年:牛哇,你真是准备得充分,我对你没有嫉妒,都是实打实付出
查看19道真题和解析
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务