本人回来亲自主持博客了,好久不写这种东西,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);
}