• 【题解】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;
    }
  • 相关阅读:
    帮你拿下 Java 面试题!
    JavaGUI编程的宿世此生
    从事Java开发可以往那些方面发展
    java初学者都要掌握的案例
    两数之和(java)
    2020年java就业前景
    300 行代码带你秒懂 Java 多线程!
    安卓程序员如何快速入门后端开发常识
    连夜整理的Java开源项目,有后台管理类、商城类、秒杀类、支付类
    Java面试题及答案,2020年最新面试题集合
  • 原文地址:https://www.cnblogs.com/twilight-sx/p/9351770.html
Copyright © 2020-2023  润新知