标签:最小 while dig sdi 线段 nbsp 全局 get 端点
[BZOJ4653][Noi2016]区间
试题描述
输入
输出
输入示例
6 3 3 5 1 2 3 4 2 2 1 5 1 4
输出示例
2
数据规模及约定
见“输入”
题解
首先将区间离散化,然后按照区间原长度排序,接下来对于区间进行滑动窗口扫描,每加入一个区间就进行一次区间加,删除一个区间就进行一次区间减,用线段树维护全局最大值,当最大值大于等于 m 时就可以更新答案了。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
int read() {
int x = 0, f = 1; char c = getchar();
while(!isdigit(c)){ if(c == ‘-‘) f = -1; c = getchar(); }
while(isdigit(c)){ x = x * 10 + c - ‘0‘; c = getchar(); }
return x * f;
}
#define maxi 500010
#define maxn 1000010
#define oo 2147483647
int n, m, num[maxn], cntn;
struct Interval {
int l, r, len;
Interval() {}
Interval(int _1, int _2, int _3): l(_1), r(_2), len(_3) {}
bool operator < (const Interval& t) const { return len < t.len; }
} ins[maxi];
int addv[maxn<<2], mxv[maxn<<2];
void pushdown(int o, int l, int r) {
if(l == r || !addv[o]){ addv[o] = 0; return ; }
int lc = o << 1, rc = lc | 1;
addv[lc] += addv[o]; mxv[lc] += addv[o];
addv[rc] += addv[o]; mxv[rc] += addv[o];
addv[o] = 0;
return ;
}
void update(int o, int l, int r, int ql, int qr, int v) {
pushdown(o, l, r);
if(ql <= l && r <= qr) {
addv[o] += v; mxv[o] += v;
return ;
}
int mid = l + r >> 1, lc = o << 1, rc = lc | 1;
if(ql <= mid) update(lc, l, mid, ql, qr, v);
if(qr > mid) update(rc, mid + 1, r, ql, qr, v);
mxv[o] = max(mxv[lc], mxv[rc]);
return ;
}
int query(int o, int l, int r) {
pushdown(o, l, r);
return mxv[o];
}
int main() {
n = read(); m = read();
for(int i = 1; i <= n; i++) {
int l = read(), r = read();
ins[i] = Interval(l, r, r - l);
num[++cntn] = l; num[++cntn] = r;
}
sort(num + 1, num + cntn + 1);
cntn = unique(num + 1, num + cntn + 1) - num - 1;
for(int i = 1; i <= n; i++)
ins[i].l = lower_bound(num + 1, num + cntn + 1, ins[i].l) - num,
ins[i].r = lower_bound(num + 1, num + cntn + 1, ins[i].r) - num;
sort(ins + 1, ins + n + 1);
int l = 1, r, ans = oo;
for(r = 1; r <= n; r++) {
update(1, 1, cntn, ins[r].l, ins[r].r, 1);
while(l <= r && query(1, 1, cntn) >= m) {
ans = min(ans, ins[r].len - ins[l].len);
update(1, 1, cntn, ins[l].l, ins[l].r, -1);
l++;
}
}
printf("%d\n", ans < oo ? ans : -1);
return 0;
}
标签:最小 while dig sdi 线段 nbsp 全局 get 端点
原文地址:http://www.cnblogs.com/xiao-ju-ruo-xjr/p/7100459.html