4552: [Tjoi2016&Heoi2016]排序
4552: [Tjoi2016&Heoi2016]排序
分析:
因为只询问一次,所以考虑二分这个数。显然是没有单调性的,但是我们可以二分所有大于等于mid的数中,是否有满足条件的x(而不是之间判断mid是否满足条件)。
那么将大于等于mid的数设为1,小于mid的数设为0,此时对区间排序就变得非常简单了,只需要线段树求一下区间内1的个数,给一段区间赋值即可。
最后判断询问的位置是否是1,如果是1,说明这个数是大于等于mid的,否者是小于mid的。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 100005; struct OPT { int opt, a, b; } Q[N]; int a[N], b[N], n, m, k; struct SegmentTree{ int sum[N << 2], tag[N << 2]; void pushdown(int rt,int len) { sum[rt << 1] = tag[rt] * (len - (len >> 1)), tag[rt << 1] = tag[rt]; sum[rt << 1 | 1] = tag[rt] * (len >> 1), tag[rt << 1 | 1] = tag[rt]; tag[rt] = -1; } void build(int l,int r,int rt) { tag[rt] = -1; if (l == r) { sum[rt] = b[l]; return ; } int mid = (l + r) >> 1; build(l, mid, rt << 1); build(mid + 1, r, rt << 1 | 1); sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void update(int l,int r,int rt,int L,int R,int v) { if (L > R) return ; if (L <= l && r <= R) { tag[rt] = v, sum[rt] = v * (r - l + 1); return ; } if (tag[rt] != -1) pushdown(rt, r - l + 1); int mid = (l + r) >> 1; if (L <= mid) update(l, mid, rt << 1, L, R, v); if (R > mid) update(mid + 1, r, rt << 1 | 1, L, R, v); sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } int query(int l,int r,int rt,int L,int R) { if (L <= l && r <= R) return sum[rt]; if (tag[rt] != -1) pushdown(rt, r - l + 1); int mid = (l + r) >> 1, res = 0; if (L <= mid) res = query(l, mid, rt << 1, L, R); if (R > mid) res += query(mid + 1, r, rt << 1 | 1, L, R); return res; } }T; bool check(int x) { for (int i = 1; i <= n; ++i) b[i] = a[i] >= x; T.build(1, n, 1); for (int i = 1; i <= m; ++i) { int cnt = T.query(1, n, 1, Q[i].a, Q[i].b); if (Q[i].opt) { T.update(1, n, 1, Q[i].a, Q[i].a + cnt - 1, 1); T.update(1, n, 1, Q[i].a + cnt, Q[i].b, 0); } else { T.update(1, n, 1, Q[i].a, Q[i].b - cnt, 0); T.update(1, n, 1, Q[i].b - cnt + 1, Q[i].b, 1); } } return T.query(1, n, 1, k, k); } int main() { n = read(), m = read(); for (int i = 1; i <= n; ++i) a[i] = read(); for (int i = 1; i <= m; ++i) Q[i].opt = read(), Q[i].a = read(), Q[i].b = read(); k = read(); int l = 1, r = n, ans = 0; while (l <= r) { int mid = (l + r) >> 1; if (check(mid)) ans = mid, l = mid + 1; else r = mid - 1; } cout << ans << "\n"; return 0; }