zoukankan      html  css  js  c++  java
  • NOI2016 区间

    题目传送门

    博客中为数不多的NOI的题目的题解……


    先将区间都离散化,再按区间长度排序
    用双指针,并线段树维护出现最多的数出现了多少次
    如果(> m)次,就移动左指针,删除最左边的区间,直到(= m)次,在这个过程中记录答案
    如果(< m)次,就移动右指针,加入右边的区间
    可以保证这样一定能找出最优解

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    #define ls p << 1
    #define rs p << 1 | 1
    #define mid ((l+r) >> 1)
    using namespace std;
    LL read() {
    	LL k = 0, f = 1; char c = getchar();
    	while(c < '0' || c > '9') {
    		if(c == '-') f = -1;
    		c = getchar();
    	}
    	while(c >= '0' && c <= '9')
    		k = k * 10 + c - 48, c = getchar();
    	return k * f;
    }
    struct zzz {
    	int l, r, len;
    }q[500010];
    bool cmp(zzz x, zzz y) {
    	return x.len < y.len;
    }
    int a[1000010], maxn = 0;
    int tree[1000010 << 2], tag[1000010 << 2];
    inline void up(int p) {
    	tree[p] = max(tree[ls], tree[rs]);
    }
    inline void down(int p) {
    	tree[ls] += tag[p]; tree[rs] += tag[p];
    	tag[ls] += tag[p], tag[rs] += tag[p];
    	tag[p] = 0;
    }
    void update(int nl, int nr, int k, int l = 1, int r = maxn, int p = 1) {
    	if(nl <= l && nr >= r) {
    		tree[p] += k; tag[p] += k; return ;
    	}
    	down(p);
    	if(nl <= mid) update(nl, nr, k, l, mid, ls);
    	if(nr > mid) update(nl, nr, k, mid+1, r, rs);
    	up(p);
    }
    int main() {
    	//freopen("2.in", "r", stdin);
    	int n = read(), m = read();
    	for(int i = 1; i <= n; ++i) {
    		q[i].l = read(), q[i].r = read(), q[i].len = q[i].r - q[i].l;
    		a[i << 1] = q[i].l, a[(i<<1) - 1] = q[i].r;
    	}
    	sort(a+1, a+n*2+1); int pos = unique(a+1, a+n*2+1) - a - 1;
    	sort(q+1, q+n+1, cmp);
    	for(int i = 1; i <= n; ++i)
    		q[i].l = lower_bound(a+1, a+pos+1, q[i].l) - a,
    		q[i].r = lower_bound(a+1, a+pos+1, q[i].r) - a,
    		maxn = max(q[i].r, maxn);
    	int l = 1, r = 0, ans = 2147483647;
    	for(r = 1; r <= n; ++r) {
    		update(q[r].l, q[r].r, 1);
    		while(tree[1] >= m) {
    			update(q[l].l, q[l].r, -1);
    			ans = min(ans, q[r].len - q[l].len);
    			++l;
    		}
    	}
    	if(ans != 2147483647) cout << ans;
    	else cout << -1;
    	return 0;
    }
    
  • 相关阅读:
    [LeetCode] Best Time to Buy and Sell Stock
    [LeetCode] Generate Parentheses
    [LeetCode] Best Time to Buy and Sell Stock 2
    [CareerCup][Google Interview] 打印组合
    [微软][笔试] 找出最大序列对
    系统之间的接口测试
    进销存业务的自定义分解
    查找数据库中所有有自增列的用户表
    由创建文件想起的。。。
    反编译想到的代码安全问题
  • 原文地址:https://www.cnblogs.com/morslin/p/11863882.html
Copyright © 2011-2022 走看看