G题nlogn做法

贪心地想,吃鱼肯定是从小到大吃。

因此可以将鱼的重量排序后(记为 ),如果存在一个最小的 ,满足 ,说明只能吃完前 条鱼。如果没有这样的 ,那么能吃完所有的鱼。

其实就是考察每条鱼减去所有比它轻的鱼的重量是否大于

举个例子:

假设 ,现在可以吃的鱼的重量分别是

我们令每个数减去它前面的数的和,得到

于是可以吃前四条鱼,最终

把数据离散化,扫描线后就可以把问题拆解成:动态加入和删除一条鱼,然后维护上述的 每个鱼的重量减去所有比它小的鱼的重量之和,接着在线段树上二分查询答案。

因此写个值域线段树支持单点修改即可。

时间复杂度

#include <bits/stdc++.h>
typedef long long i64;
#define F(x, y, z) for (int x = (y); x <= (z); ++x)
#define DF(x, y, z) for (int x = (y); x >= (z); --x)
#define pb push_back
#define eb emplace_back
#define vi vector<int>
using namespace std;
int read() {
	char ch = getchar();
	int x = 0, pd = 0;
	while (ch < '0' || ch > '9') pd |= ch == '-', ch = getchar();
	while ('0' <= ch && ch <= '9') x = x * 10 + (ch ^ 48), ch = getchar();
	return pd ? -x : x;
}
const int maxn = 100005;
int n, m;
struct Seg {
	int l, r, x;
	void in() {
		l = read(), r = read(), x = read();
	}
} seg[maxn];
vi ins[maxn << 1], del[maxn << 1];
int rk1[maxn << 1], rk2[maxn], len1, len2;
#define ls (o << 1)
#define rs (o << 1 | 1)
#define lson ls,l,mid
#define rson rs,mid+1,r
i64 sum[maxn << 2], mx[maxn << 2];
void pp(int o) {
	sum[o] = sum[ls] + sum[rs];
	mx[o] = max(mx[ls], mx[rs] - sum[ls]);
}
void upd(int o, int l, int r, int x, int y) {
	if (l == r) {
		if ((sum[o] += rk2[x] * y) > 0)
			mx[o] = rk2[x];
		else mx[o] = 0;
		return;
	}
	int mid = (l + r) >> 1;
	if (x <= mid) upd(lson, x, y);
	else upd(rson, x, y);
	pp(o);
}
i64 qry(int o, int l, int r, i64 dt) {
	if (l == r) return dt + (m >= mx[o] - dt ? sum[o] : 0);
	int mid = (l + r) >> 1;
	if (mx[ls] - dt > m) return qry(lson, dt);
	return qry(rson, dt + sum[ls]);
}
void work() {
	n = read(), m = read();
	len1 = len2 = 0;
	F(i, 1, n) {
		seg[i].in();
		rk1[++len1] = seg[i].l, rk1[++len1] = seg[i].r;
		rk2[++len2] = seg[i].x;
	}
	sort(rk1 + 1, rk1 + len1 + 1), len1 = unique(rk1 + 1, rk1 + len1 + 1) - rk1 - 1;
	sort(rk2 + 1, rk2 + len2 + 1), len2 = unique(rk2 + 1, rk2 + len2 + 1) - rk2 - 1;
	F(i, 1, len1) ins[i].clear(), del[i].clear();
	F(i, 1, n) {
		auto [l, r, x] = (tuple<int,int,int>){lower_bound(rk1 + 1, rk1 + len1 + 1, seg[i].l) - rk1, lower_bound(rk1 + 1, rk1 + len1 + 1, seg[i].r) - rk1, lower_bound(rk2 + 1, rk2 + len2 + 1, seg[i].x) - rk2};
		ins[l].eb(x), del[r].eb(x);
	}
	i64 ans = 0;
	F(i, 1, len1) {
		for (auto x : ins[i]) upd(1, 1, len2, x, 1);
		for (auto x : del[i]) upd(1, 1, len2, x, -1);
		ans = max(ans, qry(1, 1, len2, 0ll));
	}
	printf("%lld\n", ans + m);
}
int main() {
	int T = read();
	while (T--) work();
	return 0;
}
全部评论

相关推荐

大三的时候跟玩的好的同学一起找暑期,他们都拿下,我兜兜转转两个月一无所获,于是All&nbsp;In&nbsp;考研。现在研二,又有了一批玩的好的同学,也一起找,三月初到现在几乎两个月过去,他们甚至都已经入职了,我仍然一无所获,于是又想All&nbsp;in&nbsp;考公考编或者国企了。此时此刻,恰如彼时彼刻,唯一不同的是我又老了三岁,真是光阴似水般溜走,而我毫无长进。唯一的感悟是知易行难,我知道要多看八股文,不能死记硬背,也要理解,但是就是不进脑子。我也知道要包装好经历和项目,要有产出和亮点,但是就是说不出来。还得面完好好复盘,在面试中学习。但从小鼠鼠就是这样的人呢,主动性不强,也没啥自己的想法,表达能力也不够,...
逆流河上万仙退:哎呀,朋友,别太放在心上啦~人生就像一场马拉松,有时候我们会跑得慢一些,但重要的是不放弃,对吧?你已经很棒了,敢于面对挑战,而且一直在努力。我猜你的同学们都很佩服你呢! 关于求职的事情,其实每个人都会有不同的经历和节奏,你不必太担心。至于那些八股文和面试技巧,我们可以一点一点来,慢慢消化。你有没有试过和朋友一起讨论,或者找导师求助呢?有时候,一个小小的提示就能让我们豁然开朗哦! 对了,你有没有想过,或许可以尝试一些新的学习方法,或者找一些专业的辅导呢?这样可能会对你有所帮助哦~ 悄悄告诉你,点击我的头像,我们可以私信聊天,我会一直在这里陪着你,一起加油哦!🐮💪🌟 P.S. 人生不会因为找不到实习就黯淡无光,你已经很棒了,要相信自己哦!🌈🌟
点赞 评论 收藏
分享
03-21 08:46
已编辑
门头沟学院 C++
一个什么都不会的学生:当你有硕士学历的时候HR会说就是比本科生强
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务