【题解】NOI2016区间

  Two - pointer 第一题…… 大概就是对于一段连续的区间求解,使用两个指针不断卡区间的长度直到区间不满足条件吧。

  这题只要对区间以长度从小到大排一下序,然后使用两个指针指向区间。线段树维护被覆盖最多次数的节点被覆盖了多少次。如果满足条件,由于我们是在第一次判断的时候发现它满足条件的,所以最后加入的这个区间一定对于答案产生了贡献,也就是最大的区间。要使最小区间最大化,我们只需让前面的指针慢慢往后跳直到不符合条件即可。

#include <bits/stdc++.h>
using namespace std;
#define maxn 5000000
#define INF 999999999
int n, m, tot, cnt, b[maxn];
int ans = INF, num[maxn];
int mark[maxn];
map <int, int> Map;

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); }
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * k;
}

struct node
{
    int l, r, len;
    friend bool operator <(const node& a, const node& b)
    { 
        if(a.len != b.len) return a.len < b.len; 
        else if(a.l != b.l) return a.l < b.l;
        else return a.r < b.r;
    }
}A[maxn];

void push_down(int p)
{
    if(!mark[p]) return;
    num[p << 1] += mark[p], num[p << 1 | 1] += mark[p];
    mark[p << 1] += mark[p];
    mark[p << 1 | 1] += mark[p];
    mark[p] = 0;
}

void update(int p, int l, int r, int L, int R, int x)
{
    if(L <= l && R >= r) 
    {
        num[p] += x; mark[p] += x;
        return;
    }
    if(L > r || R < l) return;
    push_down(p);
    int mid = (l + r) >> 1;
    update(p << 1, l, mid, L, R, x), update(p << 1 | 1, mid + 1, r, L, R, x);
    num[p] = max(num[p << 1], num[p << 1 | 1]);
}

int main()
{
    n = read(), m = read();
    for(int i = 1; i <= n; i ++)
    {
        A[i].l = read(), A[i].r = read(), A[i].len = A[i].r - A[i].l;
        b[++ tot] = A[i].l, b[++ tot] = A[i].r;
    }
    sort(A + 1, A + 1 + n);
    sort(b + 1, b + 1 + tot); b[0] = -1;
    for(int i = 1; i <= tot; i ++) 
        if(b[i] != b[i - 1]) Map[b[i]] = ++ cnt;
    sort(A + 1, A + 1 + n);
    for(int i = 1; i <= n; i ++) A[i].l = Map[A[i].l], A[i].r = Map[A[i].r];
    for(int i = 1, j = 1; i <= n; i ++)
    {
        update(1, 1, cnt, A[i].l, A[i].r, 1);
        if(num[1] < m) continue;
        int tem = A[i].len, tem2 = 0;
        while(num[1] >= m) 
        {
            tem2 = A[j].len;
            update(1, 1, cnt, A[j].l, A[j].r, -1), j ++;
        }
        ans = min(ans, tem - tem2);
    }
    if(ans == INF) printf("-1
");
    else printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/twilight-sx/p/9351770.html