zoukankan      html  css  js  c++  java
  • 题解【bzoj4653 [NOI2016] 区间】

    先按照长度排个序,然后依次添加区间。什么是添加?设这个区间是([l,r]),添加就是把(a_l,a_{l+1},a_{l+2},{...},a_{r})都加上(1),其中(a_i)表示第(i)个位置被几个区间覆盖。拿走一个区间的含义就是把它们都减(1)。这个过程很显然可以用线段树维护。

    如果在添加到一个区间 (i) 时,有一个点被区间覆盖了(M)次,那么先更新答案,再把前面的加入过的区间一直拿直到没有一个点被覆盖(M)次。如何判断有没有点被覆盖(M)次?因为是一个一个区间加的,所以只用维护一个(a_i)的最大值,看他是否(=M)就行了。

    什么叫再把前面的加入过的区间一直拿直到没有一个点被覆盖(M)

    比如你一直添加区间到第(5)个,此时有一个点被覆盖了(M)次。这时你就将第一个区间拿出,如果此时依然有有一个点被覆盖了(M)次,那么你就拿走第二个...

    这个过程就好比一个队列,可以从后面添加区间达到一个点被覆盖了(M)次;从前面弹出区间直到没有一个点被覆盖了(M)次。

    差不多就是这样,还有注意一下(l_i,r_i leq 10^9),开线段树是要离散化的。上代码:

    #include <bits/stdc++.h>
    #define INF 1000000001
    using namespace std;
    const int N = 500500;
    int n, m, cnt, tot, ans = INF;
    struct Seg {
    	int l, r, len;
    	bool operator < (const Seg &x) const {
    		return len < x.len;
    	}
    }a[N];
    struct KEY {
    	int d, id, se;
    }key[N * 2];
    inline bool cmp1(KEY x, KEY y) {
    	return x.d < y.d;
    }
    inline bool cmp2(KEY x, KEY y) {
    	return x.id < y.id;
    }
    struct node {
    	int left, right, Max, lazy;
    	node *ch[2];
    }pool[N * 4], *root;
    inline void pushup(node *r) {
    	r->Max= max(r->ch[0]->Max, r->ch[1]->Max);
    }
    inline void pushdown(node *r) {
    	if(!r->lazy) return ;
    	r->Max += r->lazy;
    	if(r->ch[0]) r->ch[0]->lazy += r->lazy;
    	if(r->ch[1]) r->ch[1]->lazy += r->lazy;
    	r->lazy = 0; return ;
    }
    inline void build(node *r, int left, int right) {
    	r->left = left, r->right = right;
    	if(left == right) return ;
    	int mid = (left + right) >> 1;
    	node *lson = &pool[++cnt], *rson = &pool[++cnt];
    	r->ch[0] = lson, r->ch[1] = rson;
    	build(lson, left, mid), build(rson, mid + 1, right);
    }
    inline void change(node *r, int left, int right, int d) {
    	if(r->left == left && r->right == right) {
    		r->lazy += d; return ;
    	}
    	pushdown(r);
    	if(r->ch[0]->right >= right) change(r->ch[0], left, right, d);
    	else if(r->ch[1]->left <= left) change(r->ch[1], left, right, d);
    	else change(r->ch[0], left, r->ch[0]->right, d), change(r->ch[1], r->ch[1]->left, right, d);
    	pushdown(r->ch[0]), pushdown(r->ch[1]), pushup(r);
    }
    int main() {
    	scanf("%d%d", &n, &m);
    	for(int i = 1; i <= n; i++) {
    		scanf("%d%d", &a[i].l, &a[i].r);
    		a[i].len = a[i].r - a[i].l;
    		key[++tot].d = a[i].l, key[tot].id = tot;
    		key[++tot].d = a[i].r, key[tot].id = tot;
    	}
    	sort(key + 1, key + tot + 1, cmp1);
    	key[0].d = -1; key[0].se = 0;
    	for(int i = 1; i <= tot; i++)
    		if(key[i].d == key[i - 1].d) 
    			key[i].se = key[i - 1].se;
    		else key[i].se = key[i - 1].se + 1;
    	sort(key + 1, key + tot + 1, cmp2);
      for(int i = 1; i <= n; i++)
        a[i].l = key[i * 2 - 1].se, a[i].r = key[i * 2].se;
      sort(a + 1, a + n + 1);
      build(root = &pool[0], 1, 2 * n + 1);
      int pos = 1;
      change(root, a[1].l, a[1].r, 1);
      if(m == 1) ans = 0;
      for(int i = 2; i <= n; i++) {
        change(root, a[i].l, a[i].r, 1);
        while(root->Max >= m) {
      		change(root, a[pos].l, a[pos].r, -1);
      		ans = min(ans, a[i].len - a[pos].len);
      		pos++;
      	} 
      }
      if(ans == INF) ans = -1;
      printf("%d
    ", ans);
      return 0;
    }
    
  • 相关阅读:
    C 应用
    C 基本语法
    iOS
    iOS
    iOS
    iOS
    iOS
    iOS
    iOS
    iOS
  • 原文地址:https://www.cnblogs.com/acfunction/p/10051289.html
Copyright © 2011-2022 走看看