• 【洛谷 P1712】 [NOI2016]区间 (线段树+尺取)


    题目链接
    emmm看起来好像无从下手,
    (l_i,r_i)这么大,肯定是要离散化的。
    然后我们是选(m)个区间,我们先对这些区间按长度排个序也不影响。
    排序后,设我们取的(m)个区间的编号(b_1,b_2,...,b_m)
    (b_m)确定,我们肯定是要尽量使(b_1,b_2,...,b_{m-1})尽量接近(b_m)的,这样可使代价最小。
    所以,就可以尺取了。
    定义两个指针(l,r),首先(r)指针不停右移覆盖一遍扫到的区间直到满足条件有一个点被连续覆盖(m)次,怎么判断?显然维护一棵最大值线段树就好了。
    当满足条件,就让(l)指针右移直到不满足条件,更新答案。

    #include <cstdio>
    #include <algorithm>
    using std::sort;
    #define INF 2147483647
    const int MAXN = 650010;
    int n, m, q;
    char ch;
    inline int max(int a, int b){
    	return a > b ? a : b;
    }
    inline int min(int a, int b){
    	return a > b ? b : a;
    }
    inline int read(){
    	q = 0; ch = getchar();
    	while(ch < '0' || ch > '9') ch = getchar();
    	while(ch >= '0' && ch <= '9') { q = q * 10 + ch - '0'; ch = getchar(); }
    	return q;
    }
    struct Seg{
    	int l, r, len;
    	bool operator < (const Seg A) const{
    		return len < A.len;
    	}
    }s[MAXN];
    struct LSH{
    	int id, pos, val;
    	bool operator < (const LSH A) const{
    		return val < A.val;
    	}
    }p[MAXN << 1];
    int cnt, num;
    namespace SegTree{
        #define left (now << 1)
        #define right (now << 1 | 1)
    	int Max[MAXN << 2 << 1], lazy[MAXN << 2 << 1];
    	inline void pushup(int now){
    		Max[now] = max(Max[left], Max[right]);
    	}
    	inline void pushdown(int now){
    		if(lazy[now]){
    			Max[left] += lazy[now];
    			Max[right] += lazy[now];
    			lazy[left] += lazy[now];
    			lazy[right] += lazy[now];
    			lazy[now] = 0;
    		}
    	}
    	void update(int now, int l, int r, int wl, int wr, int p){
    		if(l >= wl && r <= wr){ Max[now] += p; lazy[now] += p; return; }
    		pushdown(now);
    		int mid = (l + r) >> 1;
    		if(wl <= mid) update(left, l, mid, wl, min(mid, wr), p);
    		if(wr > mid) update(right, mid + 1, r, max(mid + 1, wl), wr, p);
    		pushup(now);
    	}
    	int query(int now, int l, int r, int wl, int wr){
    		if(l >= wl && r <= wr) return Max[now];
    		int ans = 0;
    		pushdown(now);
    		int mid = (l + r) >> 1;
    		if(wl <= mid) ans = max(ans, query(left, l, mid, wl, min(mid, wr)));
    		if(wr > mid) ans = max(ans, query(right, mid + 1, r, max(mid + 1, wl), wr));
    		return ans;
    	}
    }using namespace SegTree;
    int ans = INF;
    int main(){
    	n = read(); m = read();
    	for(int i = 1; i <= n; ++i){
    		s[i].l = read(); s[i].r = read();
    		s[i].len = s[i].r - s[i].l;
    		p[++cnt].val = s[i].l; p[cnt].id = i; p[cnt].pos = 1;
    		p[++cnt].val = s[i].r; p[cnt].id = i; p[cnt].pos = 2;
    	} p[0].val = -1;
    	sort(p + 1, p + cnt + 1);
    	for(int i = 1; i <= cnt; ++i)
    		if(p[i].pos == 1)
    			if(p[i].val != p[i - 1].val)
    				s[p[i].id].l = ++num;
    			else s[p[i].id].l = num;
    		else
    			if(p[i].val != p[i - 1].val)
    				s[p[i].id].r = ++num;
    			else s[p[i].id].r = num;
    	sort(s + 1, s + n + 1);
    	int l = 1, r = 0;
    	while(r < n){
    		while(r < n && Max[1] < m){
    			++r;
    			update(1, 1, num, s[r].l, s[r].r, 1);
    		}
    		if(Max[1] < m) break;
    		int tmp;
    		while(Max[1] >= m) tmp = s[l].len, update(1, 1, num, s[l].l, s[l].r, -1), ++l;
    		ans = min(ans, s[r].len - tmp);
    	}
    	printf("%d
    ", ans == INF ? -1 : ans);
    	return 0;
    }
    
    
  • 相关阅读:
    彻底理解同步 异步 阻塞 非阻塞
    Vue2+Hbuilder 开发 H5+App 优雅调试
    Vue2+Hbuilderx打包移动端App的常见问题
    题解 loj 6102 斐波那契的最小公倍数
    题解 hdu 4336 Card Collector
    题解 luogu P3715 [HAOI2015]按位或
    python+appium【第二章-adb命令的使用】
    python+appium【第一章-环境搭建】
    python封装上传图片方法执行时有告警【ResourceWarning: Enable tracemalloc to get the object allocation traceback5】
    python需要上传图片或者上传文件的方法【autoit3】
  • 原文地址:https://www.cnblogs.com/Qihoo360/p/9739303.html
Copyright © 2020-2023  润新知