Codeforces 1555E(线段树+双指针)

本人回来亲自主持博客了,好久不写这种东西,30分钟切个2100分的水题复健一下

题目链接: Problem - 1555E - Codeforces

大致题意:在数轴[1,m]上有若干条线段,且每个线段有一个value,现在需要找一个线段集合,使得集合里的线段覆盖整个[1,m]区间,且集合里的线段value最大最小值差值尽量小。输出这个差值。

题解:

一眼水题。。。

根据线段的value从小到大排序,双指针维护value在l~r之间的线段,并实时知道是否这些线段能覆盖[1,m]区间。

这个维护的过程随便什么方法搞搞都行,线段树,分块,都行,根据数据看来可以离散化优化,但也没有比要,线段树水过去了。

具体来说每个区间维护呗覆盖的次数就行了。

挂代码:

#include <bits/stdc++.h>
const int MAXN = 3'000'00 + 10;
const int MAXM = 1'000'000 + 10;
using namespace std;
int n, m;
struct seg {
	int l, r, w;
} segs[MAXN];
struct Node {
	int cnt;
	int flag;
} segTree[MAXM * 4];
int cmp(seg a, seg b) {
	return a.w < b.w;
}
void addNode(int n, int l, int r, int pos, int num)
{
	if (segs[n].l <= l && r <= segs[n].r) {
		segTree[pos].cnt += num;
		segTree[pos].flag += num;
		return;
	}
	segTree[pos * 2].flag += segTree[pos].flag;
	segTree[pos * 2].cnt += segTree[pos].flag;
	segTree[pos * 2 + 1].flag += segTree[pos].flag;
	segTree[pos * 2 + 1].cnt += segTree[pos].flag;
	segTree[pos].flag = 0;
	int mid = (l + r) / 2;
	if (mid >= segs[n].l) addNode(n, l, mid, pos * 2, num);
	if (mid < segs[n].r) addNode(n, mid + 1, r, pos * 2 + 1, num);
	segTree[pos].cnt = min(segTree[pos * 2].cnt, segTree[pos * 2 + 1].cnt);
}
int main()
{
	scanf("%d%d", &n, &m);
	m--;
	for (int i = 0; i < n; i++) {
		scanf("%d%d%d", &segs[i].l, &segs[i].r, &segs[i].w);
		segs[i].r--;
		if (segs[i].r == m && segs[i].l == 1) {
			printf("0\n");
			return 0;
		}
	}
	sort(segs, segs + n, cmp);
	addNode(0, 1, m, 1, 1);
	int ans = 1'000'000 + 1;
	for (int l = 0, r = 0; l < n; l++){
		while (segTree[1].cnt == 0) {
			r++;
			if (r == n) break;
			addNode(r, 1, m, 1, 1);
		}
		if (r == n) break;
		ans = min(ans, segs[r].w - segs[l].w);
		addNode(l, 1, m, 1, -1);
	}
	printf("%d", ans);
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值