区间(bzoj 4653)

Description

在数轴上有 n个闭区间 [l1,r1],[l2,r2],...,[ln,rn]。现在要从中选出 m 个区间,使得这 m个区间共同包含至少一个位置。换句话说,就是使得存在一个 x,使得对于每一个被选中的区间 [li,ri],都有 li≤x≤ri。

对于一个合法的选取方案,它的花费为被选中的最长区间长度减去被选中的最短区间长度。区间 [li,ri] 的长度定义为 ri?li,即等于它的右端点的值减去左端点的值。

求所有合法方案中最小的花费。如果不存在合法的方案,输出 ?1。

Input

第一行包含两个正整数 n,m用空格隔开,意义如上文所述。保证 1≤m≤n

接下来 n行,每行表示一个区间,包含用空格隔开的两个整数 li 和 ri 为该区间的左右端点。

N<=500000,M<=200000,0≤li≤ri≤10^9

Output

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

Sample Input

6 3

3 5

1 2

3 4

2 2

1 5

1 4

Sample Output

2

/*
    不得不说,本弱是真弱啊,这道题的思路好像不是很难,但是就是想不出。
    首先将区间离散化,然后按照区间长度排序,一种暴力的方法是枚举左区间,然后枚举用线段树判定找到第一个满足条件的右区间,这样的方法是O(n^2logn)的。
    其实我们可以发现对于递增的左区间来说,第一个满足条件的右区间也是递增的,这样复杂度就降到了O(nlogn)。
*/
#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 500010
#define inf 1000000000
using namespace std;
int b[N*2],n,m;
int mx[N*8],tag[N*8];
struct node{int l,r,len;}a[N];
bool cmp(const node&x,const node&y){return x.len<y.len;}

void push_up(int k){
    mx[k]=max(mx[k*2],mx[k*2+1]);
}
void push_down(int k){
    if(!tag[k]) return;
    mx[k*2]+=tag[k];
    tag[k*2]+=tag[k];
    mx[k*2+1]+=tag[k];
    tag[k*2+1]+=tag[k];
    tag[k]=0;
}
void add(int k,int l,int r,int x,int y,int val){
    if(l>=x&&r<=y){
        mx[k]+=val;
        tag[k]+=val;
        return;
    }
    push_down(k);
    int mid=l+r>>1;
    if(x<=mid) add(k*2,l,mid,x,y,val);
    if(y>mid) add(k*2+1,mid+1,r,x,y,val);
    push_up(k);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&a[i].l,&a[i].r);
        a[i].len=a[i].r-a[i].l;
        b[i*2-1]=a[i].l;
        b[i*2]=a[i].r;
    }
    sort(b+1,b+n*2+1);
    int tot=unique(b+1,b+2*n+1)-b-1;
    for(int i=1;i<=n;i++){
        a[i].l=lower_bound(b+1,b+tot+1,a[i].l)-b;
        a[i].r=lower_bound(b+1,b+tot+1,a[i].r)-b;
    }
    sort(a+1,a+n+1,cmp);
    int tt=1,ans=inf;
    for(int i=1;i<=n;i++){
        while(mx[1]<m&&tt<=n){
            add(1,1,tot,a[tt].l,a[tt].r,1);
            tt++;
        }
        if(mx[1]>=m) ans=min(ans,a[tt-1].len-a[i].len);
        add(1,1,tot,a[i].l,a[i].r,-1);
    }
    if(ans!=inf) printf("%d",ans);
    else printf("-1");
    return 0;
}
时间: 2024-08-10 23:28:00

区间(bzoj 4653)的相关文章

AC日记——NOI2016区间 bzoj 4653

4653 思路: 线段树,指针滑动: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1000005 #define maxm 200005 #define maxn_ maxn<<2 #define INF 0x7fffffff struct TreeNodeType { int l,r,dis,mid,flag; }; struct TreeNodeType tree[maxn_]; struct Q

bzoj 4653: [Noi2016]区间

额,是不是一到了晚上IQ就--: 这个题一开始完全没有思路.(貌似脑子就没动一下) %了一下题解. 大概是决策是有单调性的,因为要去区间长度差最小,所以接排个序,然后扫描右端点,找出满足有点被覆盖m次的最右的左端点就好. 然后判断是不是有覆盖m个点的用线段树维护一下. (23333,吐槽,为什么离散化二分的时候,把左端点搞成0,右端点搞成L就会RE??excuse me?!!) 1 #include<bits/stdc++.h> 2 #define LL long long 3 #define

[BZOJ 1112] [POI2008] 砖块Klo 【区间K大】

题目链接:BZOJ - 1112 题目分析 枚举每一个长度为k的连续区间,求出这个区间的最优答案,更新全局答案. 可以发现,这个区间的所有柱子最终都变成这k个数的中位数时最优,那么我们就需要查询这个区间的中位数了. 找到中位数之后,我们还应该求出这个区间内小于中位数的数的和,大于中位数的数的和,从而求出操作步数. 这些需要求的值可以用线段树或平衡树来写,我写的是线段树,但是实际上这是一道POI的题目,在MAIN上的空间限制只有35MB,线段树应该是不行的. 因为平衡树只需要 O(n) 空间,所以

BZOJ 1090 字符串折叠(区间DP)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1090 题意:字符串AAAAAAAAAABABABCCD的最短折叠为9(A)3(AB)CCD,注意数字的长度和圆括号都算最后长度.求一种折叠方式使得总长度最小. 思路:f[L][R]=min(R-L+1,f[L][i]+f[i+1][R]),另外若[L,R]能由[i+1,R]重复若干次,则也可用折叠后的长度更新f[L][R]. char s[N]; int f[N][N],n; int

BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树

之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池..尼玛终于过了..附zju2112代码于后. bzoj倒是过了,1A的感觉还是很爽的..可是时间不好看..这就是所谓\(O(nlog^3n)\)的复杂度的可怜之处么? 写挂的地方: insert一定要是传地址指针进去. delete时先把地址指针delete掉,最后把是地址指针指向左儿子or右儿子

[BZOJ 1068] [SCOI2007] 压缩 【区间 DP 】

题目链接:BZOJ - 1068 题目分析 这种区间 DP 之前就做过类似的,也是字符串压缩问题,不过这道题稍微复杂一些. 需要注意如果某一段是 S1S1 重复,那么可以变成 M + Solve(S1) + R ,不过这个 Solve(S1) 中不能在中间有 M ,否则后面的 R 向前找到的 M 就不再是开头的 M 了. 代码 #include <iostream> #include <cstdio> #include <cstring> #include <al

【BZOJ】1012: [JSOI2008]最大数maxnumber(树状数组+区间最值)

http://www.lydsy.com/JudgeOnline/problem.php?id=1012 树状数组原来我只懂得sum和add的操作,今天才知道可以有求区间最值的操作,我学习了一下写了个,1a了. 区间最值其实和区间求和差不多,就是将sum数组的含义转移到max,然后通过特定的区间更新max. 在区间求和中,当我们维护max[i]的时候,要找到它前面所有的max[j]来更新,在这里因为是树状数组,所以可以降成一个log级,画图可知,max[i]需要的max只有max[i-2^0],

bzoj 3744 Gty的妹子序列 区间逆序对数(在线) 分块

题目链接 题意 给定\(n\)个数,\(q\)个询问,每次询问\([l,r]\)区间内的逆序对数. 强制在线. 思路 参考:http://www.cnblogs.com/candy99/p/6579556.html 离线的话就如上一题bzoj 3289 Mato的文件管理,可以直接用 莫队 搞,在线的话怎么办呢? 分块大法好. 1 预处理出两个信息: \(f[i][j]\):从 第\(i\)块开始位置 到 位置\(j\) 这段区间的逆序对数 \(s[i][j]\):前\(i\)块中\(\leq

[BZOJ 4350]括号序列再战猪猪侠 题解(区间DP)

[BZOJ 4350]括号序列再战猪猪侠 Description 括号序列与猪猪侠又大战了起来. 众所周知,括号序列是一个只有(和)组成的序列,我们称一个括号 序列S合法,当且仅当: 1.( )是一个合法的括号序列. 2.若A是合法的括号序列,则(A)是合法的括号序列. 3.若A,B是合法的括号序列,则AB是合法的括号序列. 我们考虑match[i]表示从左往右数第i个左括号所对应的是第几个右 括号,现在他得到了一个长度为2n的括号序列,给了你m个信息,第i 个信息形如ai,bi,表示match