1. 程式人生 > >BZOJ4653(區間離散化+線段樹+決策單調尺取)

BZOJ4653(區間離散化+線段樹+決策單調尺取)

ini using mat 過去 type section lib else 優化

寫得很好的題解

一眼過去很像是:排序,然後從前向後掃,有這個區間時插到樹裏,過去以後再刪除。然後事實也是這樣做的……

具體起來:

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 }

BZOJ4653(區間離散化+線段樹+決策單調尺取)