[NOI 2016] 区间

[题目链接]

         https://www.lydsy.com/JudgeOnline/problem.php?id=4653

[算法]

        首先将区间按长度排序

        那么 , 满足条件的一定是一段连续的区间 , [Li , Ri] , [Li+1,Ri+1] ... [Lj , Rj]

        我们不妨枚举每一个L ,  不难发现当L递增时 , 满足条件的 , 最小的R同样是单调递增的 , 不妨用Two-Pointers计算这个最小的R并更新答案

        我们还需用线段树维护当前被覆盖最多次的位置被覆盖了多少次

        由于每个位置都会被访问并更新一次 , 故时间复杂度为 : O(NlogN)

[代码]

        

#include<bits/stdc++.h>
using namespace std;
#define MAXN 500010
#define MAXM 200010
const int inf = 2e9;

struct range
{
        int l , r;
} a[MAXN];

int n , m , len;
int tmp[MAXN << 1] , l[MAXN] , r[MAXN];

struct Segment_Tree
{
        struct Node
        {
                int l , r;
                int mx , tag;
        } Tree[MAXN << 4];
        inline void build(int index , int l , int r)
        {    
                Tree[index].l = l;
                Tree[index].r = r;
                Tree[index].mx = Tree[index].tag = 0;
                if (l == r) return;
                int mid = (l + r) >> 1;
                build(index << 1 , l , mid);
                build(index << 1 | 1 , mid + 1 , r);
        }
        inline void pushdown(int index)
        {
                Tree[index << 1].mx += Tree[index].tag;
                Tree[index << 1 | 1].mx += Tree[index].tag;
                Tree[index << 1].tag += Tree[index].tag;
                Tree[index << 1 | 1].tag += Tree[index].tag;
                Tree[index].tag = 0;
        }
        inline void update(int index)
        {
                Tree[index].mx = max(Tree[index << 1].mx , Tree[index << 1 | 1].mx);
        }
        inline void modify(int index , int l ,int r , int value)
        {
                if (Tree[index].l == l && Tree[index].r == r)
                {
                        Tree[index].mx += value;
                        Tree[index].tag += value;
                        return;
                }
                pushdown(index);
                int mid = (Tree[index].l + Tree[index].r) >> 1;
                if (mid >= r) modify(index << 1 , l , r , value);
                else if (mid + 1 <= l) modify(index << 1 | 1 , l , r , value);
                else
                {
                        modify(index << 1 , l , mid , value);
                        modify(index << 1 | 1 , mid + 1 , r , value);
                }
                update(index);
        }
        inline int query()
        {
                return Tree[1].mx;
        }
} SGT;
template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
    x *= f;
}
inline bool cmp(range a , range b)
{
        return a.r - a.l < b.r - b.l;
}

int main()
{
        
        read(n); read(m);
        for (int i = 1; i <= n; i++)
        {
                read(a[i].l);
                read(a[i].r);
                tmp[i * 2 - 1] = a[i].l;
                tmp[i * 2] = a[i].r;        
        }
        sort(tmp + 1 , tmp + 2 * n + 1);
        len = unique(tmp + 1 , tmp + 2 * n + 1) - tmp - 1;
        sort(a + 1 , a + n + 1 , cmp);
        for (int i = 1; i <= n; i++)
        {
                l[i] = lower_bound(tmp + 1 , tmp + len + 1 , a[i].l) - tmp;
                r[i] = lower_bound(tmp + 1 , tmp + len + 1 , a[i].r) - tmp;        
        }
        SGT.build(1 , 1 , len);
        int ans = inf , rgt = 0;
        for (int i = 1; i <= n; i++)
        {
                bool flg = false;
                while (rgt <= n)
                {
                        if (SGT.query() >= m) 
                        {    
                                flg = true;
                                break;
                        }
                        ++rgt;
                        if (rgt > n) break;
                        SGT.modify(1 , l[rgt] , r[rgt] , 1);
                }
                if (flg) chkmin(ans , (tmp[r[rgt]] - tmp[l[rgt]]) - (tmp[r[i]] - tmp[l[i]]));
                else break;
                SGT.modify(1 , l[i] , r[i] , -1);
        }
        printf("%d\n" , ans != inf ? ans : -1);
        
        return 0;
    
}

 

posted @ 2018-10-28 20:33  evenbao  阅读(174)  评论(0编辑  收藏  举报