洛谷 P2824 [HEOI2016/TJOI2016]排序
传送门
题意
给出一个 $1$ 到 $n$ 的全排列,现在对这个全排列序列进行 $m$ 次局部排序,排序分为两种:$(0,l,r)$ 表示将区间 $[l,r]$ 的数字升序排序,$(1,l,r)$ 表示将区间 $[l,r]$ 的数字降序排序。
最后询问第 $q$ 位置上的数字。$n,m\leq 30000$ 。
题解
你可以看到,最后我们只询问一个固定位置上的数字。
我们来考虑二分这个数字的值 $x$ ,然后建一颗线段树,我们在开始的时候把所有 $\geq x$ 的数字标为 $1$ ,其他数字标为 $0$ 。
然后,我们就可以用线段树区间修改、区间查询和的方法对一段区间排序了。最后我们查询 $q$ 位置,如果结果为 $1$ ,说明 $q$ 上的数组 $\geq x$。
时间复杂度:$\mathcal O\left(m\mathrm{lg}^2 n\right)$
上代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 struct SegmentTree{ 5 #define segc int M = (l + r) >> 1, lc = p << 1, rc = lc | 1 6 bool one[400005], zero[400005]; int sum[400005], n; 7 void _down(int p, int l, int r) { 8 segc; if (one[p]) { 9 sum[lc] = M-l+1, sum[rc] = r-M; 10 zero[lc] = zero[rc] = 0; one[lc] = one[rc] = 1; 11 } 12 if (zero[p]) { 13 sum[lc] = sum[rc] = 0; 14 zero[lc] = zero[rc] = 1; one[lc] = one[rc] = 0; 15 } 16 one[p] = zero[p] = false; 17 } 18 void _set(int p, int l, int r, int x, int y, int val) { 19 if (l == x && r == y) { 20 if (val) one[p] = 1, zero[p] = 0; 21 else one[p] = 0, zero[p] = 1; 22 sum[p] = val ? (r-l+1) : 0; 23 return; 24 } 25 segc; _down(p, l, r); 26 if (y <= M) _set(lc, l, M, x, y, val); 27 else if (x > M) _set(rc, M+1, r, x, y, val); 28 else _set(lc, l, M, x, M, val), _set(rc, M+1, r, M+1, y, val); 29 sum[p] = sum[lc] + sum[rc]; 30 } 31 int _query(int p, int l, int r, int x, int y) { 32 if (l == x && r == y) return sum[p]; 33 segc; _down(p, l, r); 34 if (y <= M) return _query(lc, l, M, x, y); 35 else if (x > M) return _query(rc, M+1, r, x, y); 36 else return _query(lc, l, M, x, M) + _query(rc, M+1, r, M+1, y); 37 } 38 inline void init(int N) { 39 n = N; 40 memset(one, 0, sizeof(one)); memset(zero, 0, sizeof(zero)); 41 memset(sum, 0, sizeof(sum)); 42 } 43 inline void set(int l, int r, int v) { l <= r ? _set(1, 1, n, l, r, v) : void(0); } 44 inline int query(int l, int r) { return _query(1, 1, n, l, r); } 45 } ST; 46 47 int n, m, Q, a[100005], L[100005], R[100005], op[100005]; 48 49 bool check(int x) { 50 ST.init(n); 51 for (int i=1; i<=n; i++) ST.set(i, i, a[i] >= x); 52 for (int i=1; i<=m; i++) { 53 int ss = ST.query(L[i], R[i]); 54 if (op[i]) { 55 ST.set(L[i], L[i]+ss-1, 1); ST.set(L[i]+ss, R[i], 0); 56 } else { 57 ST.set(R[i]-ss+1, R[i], 1); ST.set(L[i], R[i]-ss, 0); 58 } 59 } 60 return ST.query(Q, Q); 61 } 62 63 int main() { 64 ios :: sync_with_stdio(false); 65 cin >> n >> m; 66 for (int i=1; i<=n; i++) { 67 cin >> a[i]; 68 } 69 for (int i=1; i<=m; i++) { 70 cin >> op[i] >> L[i] >> R[i]; 71 } 72 cin >> Q; 73 int l = 1, r = n, ans; 74 while (l <= r) { 75 int mid = (l + r) >> 1; 76 if (check(mid)) l = mid + 1, ans = mid; 77 else r = mid - 1; 78 } 79 cout << ans << endl; 80 return 0; 81 }