[洛谷P2824][HEOI2016/TJOI2016]排序
题目大意:一个全排列,两种操作:
1. $0\;l\;r:$把$[l,r]$升序排序
2. $1\;l\;r:$把$[l,r]$降序排序
最后询问第$k$位是什么
题解:二分答案,把比这个数大的赋成$1$,否则为$0$,线段树区间和和区间赋$01$,最后判断第$k$位是$0$是$1$,若为$1$则还可以变大,否则变小
卡点:修改后没有$update$
C++ Code:
#include <cstdio> #include <cctype> namespace __R { int x, ch; inline int read() { ch = getchar(); while (isspace(ch)) ch = getchar(); for (x = ch & 15, ch = getchar(); isdigit(ch); ch = getchar()) x = x * 10 + (ch & 15); return x; } } using __R::read; #define maxn 100010 int n, m, q; int s[maxn], op[maxn], L[maxn], R[maxn]; namespace SgT { int V[maxn << 2], tg[maxn << 2]; int num, L, R; void build(int rt, int l, int r) { tg[rt] = -1; if (l == r) { V[rt] = s[l] > num; return ; } int mid = l + r >> 1; build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r); V[rt] = V[rt << 1] + V[rt << 1 | 1]; } void build(int __num) { num = __num; build(1, 1, n); } inline void pushdown(int rt, int len) { int &__tg = tg[rt]; V[rt << 1] = (len + 1 >> 1) * __tg; tg[rt << 1] = __tg; V[rt << 1 | 1] = (len >> 1) * __tg; tg[rt << 1 | 1] = __tg; __tg = -1; } int __query(int rt, int l, int r) { if (L <= l && R >= r) return V[rt]; int mid = l + r >> 1, ans = 0; if (~tg[rt]) pushdown(rt, r - l + 1); if (L <= mid) ans = __query(rt << 1, l, mid); if (R > mid) ans += __query(rt << 1 | 1, mid + 1, r); return ans; } int query(int __L, int __R) { L = __L, R = __R; return __query(1, 1, n); } void __modify(int rt, int l, int r) { if (L <= l && R >= r) { V[rt] = num * (r - l + 1); tg[rt] = num; return ; } int mid = l + r >> 1; if (~tg[rt]) pushdown(rt, r - l + 1); if (L <= mid) __modify(rt << 1, l, mid); if (R > mid) __modify(rt << 1 | 1, mid + 1, r); V[rt] = V[rt << 1] + V[rt << 1 | 1]; } void modify(int __L, int __R, int __num) { L = __L, R = __R, num = __num; __modify(1, 1, n); } } bool check(int mid) { SgT::build(mid); for (int i = 1; i <= m; i++) { int _1 = SgT::query(L[i], R[i]), _0 = R[i] - L[i] + 1 - _1; if (op[i]) { SgT::modify(L[i], L[i] + _1 - 1, 1); SgT::modify(L[i] + _1, R[i], 0); } else { SgT::modify(L[i], L[i] + _0 - 1, 0); SgT::modify(L[i] + _0, R[i], 1); } } return SgT::query(q, q); } int main() { n = read(), m = read(); for (int i = 1; i <= n; i++) s[i] = read(); for (int i = 1; i <= m; i++) { op[i] = read(), L[i] = read(), R[i] = read(); } q = read(); int l = 1, r = n, ans = 1; while (l <= r) { int mid = l + r >> 1; if (check(mid)) l = mid + 1; else { r = mid - 1; ans = mid; } } printf("%d\n", ans); return 0; }