【Luogu P2824】[HEOI2016/TJOI2016]排序
阿新 • • 發佈:2020-07-23
題目大意:
給出一個 \(1\) 到 \(n\) 的排列,\(m\) 次操作讓某區間升序排或降序排,問 \(q\) 位置最後是多少。
正文:
本題十分巧妙,二分一個 \(k\),排列裡大於 \(k\) 的數為 1,否則為 0,線段樹維護這個 01串,進行排序,再根據 \(q\) 的位置調整二分範圍。
程式碼:
struct SegmentTree { struct Node { int l, r; } SMT[N << 2]; int lazy[N << 2], val[N << 2]; void pushup(int x) { val[x] = val[x << 1 | 1] + val[x << 1]; } void pushdown(int x) { if(~lazy[x]) { val[x << 1] = lazy[x] * (SMT[x << 1].r - SMT[x << 1].l + 1); val[x << 1 | 1] = lazy[x] * (SMT[x << 1 | 1].r - SMT[x << 1 | 1].l + 1); lazy[x << 1] = lazy[x]; lazy[x << 1 | 1] = lazy[x]; lazy[x] = -1; } } void prework() { memset(lazy, -1, sizeof lazy); memset(val, 0, sizeof val); } void build(int x, int l, int r, int k) { SMT[x].l = l, SMT[x].r = r; if(l == r) { val[x] = a[l] >= k; return ; } int mid = (l + r) >> 1; build(x << 1, l, mid, k); build(x << 1 | 1, mid + 1, r, k); pushup(x); } void change(int p, int l, int r, int x, int y, int vall) { if (x <= l && r <= y) { val[p] = vall * (r - l + 1); lazy[p] = vall; return ; } if (l > y || r < x) return ; pushdown(p); int mid = (l + r) >> 1; change(p << 1, l, mid, x, y, vall); change(p << 1 | 1, mid + 1, r, x, y, vall); pushup(p); } int query(int p , int l, int r, int x, int y) { if (x <= l && r <= y) { return val[p]; } if (l > y || r < x) return 0; pushdown(p); int mid = (l + r) >> 1; return query(p << 1, l, mid, x, y) + query(p << 1 | 1, mid + 1, r, x, y); } }smt; int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf ("%d", &a[i]); for (int i = 1; i <= m ; i++) scanf ("%d%d%d", &input[i][0], &input[i][1], &input[i][2]); scanf ("%d", &q); int l = 1, r = n, ans, mid; while(l <= r) { mid = (l + r) >> 1; smt.prework(); smt.build(1, 1, n, mid); for (int i = 1; i <= m; i++) { int cntOne = smt.query(1, 1, n, input[i][1], input[i][2]); if (input[i][0]) { smt.change(1, 1, n, input[i][1], input[i][1] + cntOne - 1, 1); smt.change(1, 1, n, input[i][1] + cntOne, input[i][2], 0); }else { smt.change(1, 1, n, input[i][2] - cntOne + 1, input[i][2], 1); smt.change(1, 1, n, input[i][1], input[i][2] - cntOne, 0); } } int k = smt.query(1, 1, n, q, q); if(k) ans = mid, l = mid + 1;else r = mid - 1; } printf("%d\n", ans); return 0; }