zoukankan      html  css  js  c++  java
  • [BZOJ4653][Noi2016]区间

    [BZOJ4653][Noi2016]区间

    试题描述

    在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。
    对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri−li,即等于它的右端点的值减去左端点的值。
    求所有合法方案中最小的花费。如果不存在合法的方案,输出 −1。

    输入

    第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n
    接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。
    N<=500000,M<=200000,0≤li≤ri≤10^9

    输出

    只有一行,包含一个正整数,即最小花费。

    输入示例

    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
    ", ans < oo ? ans : -1);
    	
    	return 0;
    }
    
  • 相关阅读:
    关于uoloadify不能显示效果原因(thinkphp5仿百度糯米)
    thinkphp3.2.3中$this->assign
    PDO
    类的声明 只能有属性和方法(属性没有括号,方法有括号)
    怎删改查
    JS鼠标事件大全
    建表以及 增。删。改。查
    建表、添加数据及数据查询
    html框架
    表的求和及计算
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/7100459.html
Copyright © 2011-2022 走看看