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 }