题意:
给出一堆区间,要你选出m个区间使得至少一个点都被覆盖,并且此时花费的代价是最长的区间长减去最短的区间长。
问最小的代价。
做法:
我们考虑一中区间的入场顺序,按照长度从小到大。
我们选出的区间肯定是连续的一段,于是我们用两个指针维护开头和结尾。
进来一段区间,就在线段树上把这一段加一,然后假如某一时刻,有一个点到达了m,就说明这连续一段的区间是可行的就可以更新答案,并且头指针++,看能不能继续更新。
于是扫一遍就好了。
易错点:
线段树下标不要搞错,是离散化以后的数的总数(原来写成n了样例挂了好几发)。
代码:
/*************************************************************
Problem: bzoj 4653 [Noi2016]区间
User: fengyuan
Language: C++
Result: Accepted
Time: 7324 ms
Memory: 48172 kb
Submit_Time: 2018-01-05 10:53:31
*************************************************************/
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cctype>
#define mid (l+r>>1)
#define lc (o<<1)
#define rc (o<<1|1)
using namespace std;
typedef long long LL;
inline LL read()
{
char ch = getchar(); LL x = 0; int op = 1;
for (; !isdigit(ch); ch = getchar()) if (ch == '-') op = -1;
for (; isdigit(ch); ch = getchar()) x = x*10+ch-'0';
return op*x;
}
const int N = 1000010;
int n, m, tot;
int mx[N<<2], tag[N<<2], num[N];
struct Node{
int l, r, len;
}a[N];
const bool cmp(const Node &x, const Node &y) { return x.len < y.len; }
inline void add(int o, int l, int r, int x, int y, int v)
{
if(l == x && r == y) { tag[o] += v; mx[o] += v; return; }
if(y <= mid) add(lc, l, mid, x, y, v);
else if(x > mid) add(rc, mid+1, r, x, y, v);
else add(lc, l, mid, x, mid, v), add(rc, mid+1, r, mid+1, y, v);
mx[o] = max(mx[lc], mx[rc]) + tag[o];
}
int main()
{
n = read(), m = read();
for(int i = 1; i <= n; i ++) {
a[i].l = read(), a[i].r = read();
num[++ tot] = a[i].l; num[++ tot] = a[i].r;
a[i].len = a[i].r-a[i].l+1;
}
sort(a+1, a+1+n, cmp);
sort(num+1, num+1+tot); tot = unique(num+1, num+1+tot) - num-1;
for(int i = 1; i <= n; i ++) {
a[i].l = lower_bound(num+1, num+1+tot, a[i].l) - num;
a[i].r = lower_bound(num+1, num+1+tot, a[i].r) - num;
}
int h = 1, t = 0; int ans = 1e9;
while(h <= n) {
while(t < n && mx[1] < m) {
t ++;
add(1, 1, tot, a[t].l, a[t].r, 1);
}
if(t == n && mx[1] < m) break;
ans = min(ans, a[t].len - a[h].len);
add(1, 1, tot, a[h].l, a[h].r, -1); h ++;
}
if(ans == 1e9) puts("-1"); else printf("%d\n", ans);
return 0;
}