bzoj4653: [Noi2016]区间



题目链接

bzoj4653: [Noi2016]区间

题解

区间长度排序后维护一个满足m条件的滑动区间

代码

#include<cstdio> 
#include<vector> 
#include<algorithm> 
#define gc getchar() 
#define pc putchar 
#define LL long long 
#define pb push_back
inline int read() { 
    int x = 0,f = 1; 
    char c = gc; 
    while(c < '0' || c > '9')c = gc; 
    while(c <= '9' && c >= '0') x = x * 10 + c -'0',c = gc; 
    return x * f; 
} 
void print(LL x) { 
    if(x < 0) {
        pc('-'); x = -x; 
    } 
    if(x >= 10) print(x / 10); 
    pc(x % 10 + '0'); 
} 
const int maxn = 500007; 
struct ZZX { 
    int l,r,len; 
    bool operator < (const ZZX &a) const {
        return len < a.len; 
    } 
} a[maxn]; 
int n,m; 
int b[maxn << 1]; 
int t[(maxn * 2) << 2],tag[(maxn * 2) << 2]; 
#define ls x << 1,l,mid
#define rs x << 1 | 1,mid + 1,r 
void modify(int x,int l,int r,int L,int R,int k) {
    if(l >= L && r <= R) { 
        t[x] +=  k; 
        tag[x] += k; 
        return; 
    } 
    int mid = l + r >> 1; 
    if(tag[x] != 0) { 
        t[x << 1] += tag[x]; 
        t[x << 1 | 1] +=  tag[x]; 
        tag[x << 1] += tag[x]; 
        tag[x << 1 | 1] += tag[x]; 
        tag[x] = 0; 
    } 
    
    if(L <= mid) modify(ls,L,R,k); 
    if(R >  mid) modify(rs,L,R,k); 
    t[x] = std::max(t[x << 1],t[x << 1 | 1]); 
} 
int main() { 
    //freopen("11.in","r",stdin); 
    n = read(); m = read(); 
    int tot = 0; 
    for(int i = 1;i <= n;++ i) 
        a[i].l = read(),a[i].r = read(),
        a[i].len = a[i].r - a[i].l + 1,  
        b[ ++ tot] = a[i].l,b[++ tot] = a[i].r; 
    std::sort(b + 1,b + tot + 1); 
    tot = std::unique(b + 1,b + tot + 1) - b - 1; 
    for(int i = 1;i <= n;++ i) 
        a[i].l = std::lower_bound(b + 1,b + tot + 1,a[i].l) - b, 
        a[i].r = std::lower_bound(b + 1,b + tot + 1,a[i].r) - b; 
    std::sort(a + 1,a + n + 1); 
    #define INF 0x3f3f3f3f 
    int ans = INF; 
    for(int l = 1,r = 1;r <= n;++ r) { 
        while(t[1] < m && r <= n) {
            modify(1,1,tot,a[r].l,a[r].r,1); 
            ++ r;   
        } 
        if(t[1] < m) break; 
        -- r; 
        while(t[1] >= m) modify(1,1,tot,a[l].l,a[l].r,-1) , ++ l; 
        ans = std::min(ans,a[r].len - a[l - 1].len); 
    } 
    print(ans == INF ? -1 : ans); 
    return 0; 
}   

转载于:https://www.cnblogs.com/sssy/p/9789196.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值