BZOJ4653(区间离散化+线段树+决策单调尺取)

写得很好的题解

一眼过去很像是:排序,然后从前向后扫,有这个区间时插到树里,过去以后再删除。然后事实也是这样做的……

具体起来:

1.如果考虑暴力的话,一种想法是枚举左端和右端要选取的区间(如果我们按长度排序的话),那么只要发现当前选取的这些从左到右的区间可以得到m及以上就可以了,没必要特地考虑具体选哪些,然后ans = min(ans, 右len - 左len)即可。

2.判断这些区间是否可行的方法是:出现一个区间就把区间内所有点+1,线段树维护最大值,所以segment[1].maxx >= m时该区间可行,然后1e9太大,把每个区间端点离散化一下。

3.复杂度太大,优化手法是发现如果当前的左端区间和右端区间都合法的话,因为我们是按照长度排序的,所以右端区间没理由往右移了,只会让答案更差。所以枚举左端即可,右端类似尺取的方法即可。然后就是常见手法,遇到一个新的r就插进树里+1,路过一个l就从树里-1。

  1 #pragma comment(linker, "/STACK:1024000000,1024000000")
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <cctype>
  8 #include <climits>
  9 #include <iostream>
 10 #include <iomanip>
 11 #include <algorithm>
 12 #include <string>
 13 #include <sstream>
 14 #include <stack>
 15 #include <queue>
 16 #include <set>
 17 #include <map>
 18 #include <vector>
 19 #include <list>
 20 #include <fstream>
 21 #include <bitset>
 22 #define init(a, b) memset(a, b, sizeof(a))
 23 #define rep(i, a, b) for (int i = a; i <= b; i++)
 24 #define irep(i, a, b) for (int i = a; i >= b; i--)
 25 #define ls(p) (p) << 1
 26 #define rs(p) (p) << 1 | 1
 27 using namespace std;
 28 
 29 typedef double db;
 30 typedef long long ll;
 31 typedef unsigned long long ull;
 32 typedef pair<int, int> P;
 33 const int inf = 0x3f3f3f3f;
 34 const ll INF = 1e18;
 35 
 36 template <typename T> void read(T &x) {
 37     x = 0;
 38     int s = 1, c = getchar();
 39     for (; !isdigit(c); c = getchar())
 40         if (c == '-')    s = -1;
 41     for (; isdigit(c); c = getchar())
 42         x = x * 10 + c - 48;
 43     x *= s;
 44 }
 45 
 46 template <typename T> void write(T x) {
 47     if (x < 0)    x = -x, putchar('-');
 48     if (x > 9)    write(x / 10);
 49     putchar(x % 10 + '0');
 50 }
 51 
 52 template <typename T> void writeln(T x) {
 53     write(x);
 54     puts("");
 55 }
 56 
 57 const int maxn = 1e6 + 5;
 58 
 59 int n, m, c[maxn], tot, ans = inf;
 60 struct Section {
 61     int l, r, len;
 62 
 63     bool operator < (const Section y) const {
 64         return len < y.len;
 65     }
 66 }a[maxn];
 67 
 68 
 69 struct Node {
 70     int l, r, maxx, tag;
 71 }t[maxn << 2];
 72 
 73 void build(int l, int r, int p) {
 74     t[p].l = l, t[p].r = r;
 75     if (l == r) {
 76         t[p].maxx = t[p].tag = 0;
 77         return;
 78     }
 79     int mid = (l + r) >> 1;
 80     build(l, mid, ls(p));
 81     build(mid + 1, r, rs(p));
 82 }
 83 
 84 void Push_down(int p) {
 85     if (t[p].tag) {
 86         t[ls(p)].maxx += t[p].tag;
 87         t[rs(p)].maxx += t[p].tag;
 88         t[ls(p)].tag += t[p].tag;
 89         t[rs(p)].tag += t[p].tag;
 90         t[p].tag = 0;
 91     }
 92 }
 93 
 94 void Update(int l, int r, int p, int k) {
 95     if (l <= t[p].l && t[p].r <= r) {
 96         t[p].maxx += k;
 97         t[p].tag += k;
 98         return;
 99     }
100     Push_down(p);
101     int mid = (t[p].l + t[p].r) >> 1;
102     if (l <= mid)    Update(l, r, ls(p), k);
103     if (mid < r)    Update(l, r, rs(p), k);
104     t[p].maxx = max(t[ls(p)].maxx, t[rs(p)].maxx);
105 }
106 
107 int main() {
108     read(n), read(m);
109     rep(i, 1, n) {
110         read(a[i].l);
111         read(a[i].r);
112         a[i].len = a[i].r - a[i].l;
113         c[++tot] = a[i].l;
114         c[++tot] = a[i].r;
115     }
116     //离散化
117     sort(c + 1, c + 1 + tot);
118     tot = unique(c + 1, c + 1 + tot) - c - 1;
119     rep(i, 1, n) {
120         a[i].l = lower_bound(c + 1, c + 1 + tot, a[i].l) - c;
121         a[i].r = lower_bound(c + 1, c + 1 + tot, a[i].r) - c;
122     }
123     sort(a + 1, a + 1 + n);
124     //线段树维护
125     build(1, tot, 1);
126     for (int l = 1, r = 0; l <= n; l++) {
127         while (t[1].maxx < m && r < n) {
128             ++r;
129             Update(a[r].l, a[r].r, 1, 1);
130         }
131         if (t[1].maxx == m) {
132             ans = min(ans, a[r].len - a[l].len);
133         } else    break;
134         Update(a[l].l, a[l].r, 1, -1);
135     }
136 
137     if (ans == inf)    puts("-1");
138     else    writeln(ans);
139     return 0;
140 }
原文地址:https://www.cnblogs.com/AlphaWA/p/10582646.html