https://www.hackerrank.com/contests/101hack38/challenges/sorted-subsegments/problem
首先要注意到可以二分答案,比如当前位置是4,二分答案是2,是可以的,往大的找找就好。
然后把 >= 2的变成1, < 2的变成0,然后就对这个01串排序了。
01串排序可以用线段树加速,因为区间里1的个数是固定的,排序区间L, R,只相当于把区间里1的个数全部往右移动。
然后就可以直接用线段树查找区间总和 + 覆盖即可。
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; #define lson L, mid, cur << 1 #define rson mid + 1, R, cur << 1 | 1 #define root 1, n, 1 const int maxn = 75000 + 20; int sum[maxn << 2], add[maxn << 2]; int a[maxn]; int n, q, k; struct Node { int L, R; }query[maxn]; void pushUp(int cur) { sum[cur] = sum[cur << 1] + sum[cur << 1 | 1]; } void build(int L, int R, int cur, int val) { if (L == R) { sum[cur] = a[L] >= val; return ; } int mid = (L + R) >> 1; build(lson, val); build(rson, val); pushUp(cur); } void pushDown(int cur, int has) { if (add[cur] != -1) { add[cur << 1] = add[cur << 1 | 1] = add[cur]; sum[cur << 1] = (has - (has >> 1)) * add[cur]; sum[cur << 1 | 1] = (has >> 1) * add[cur]; add[cur] = -1; } } int ask(int be, int en, int L, int R, int cur) { if (L >= be && R <= en) return sum[cur]; pushDown(cur, R - L + 1); int mid = (L + R) >> 1; int ans = 0; if (be <= mid) ans += ask(be, en, lson); if (en > mid) ans += ask(be, en, rson); return ans; } void upDate(int be, int en, int val, int L, int R, int cur) { if (be > en) return; if (L >= be && R <= en) { add[cur] = val; sum[cur] = (R - L + 1) * val; return; } pushDown(cur, R - L + 1); int mid = (L + R) >> 1; if (be <= mid) upDate(be, en, val, lson); if (en > mid) upDate(be, en, val, rson); pushUp(cur); } bool check(LL val) { build(root, val); memset(add, -1, sizeof add); for (int i = 1; i <= q; ++i) { int has = query[i].R - query[i].L + 1; int one = ask(query[i].L, query[i].R, root); upDate(query[i].L, query[i].L + has - one - 1, 0, root); upDate(query[i].L + has - one, query[i].R, 1, root); } return ask(k, k, root); } void work() { scanf("%d%d%d", &n, &q, &k); ++k; for (int i = 1; i <= n; ++i) { scanf("%d", a + i); } for (int i = 1; i <= q; ++i) { scanf("%d%d", &query[i].L, &query[i].R); query[i].L++, query[i].R++; } // build(root, 4); // upDate(1, 3, 0, root); // upDate(4, 4, 1, root); // printf("%d ", ask(1, 1, root)); LL be = -1e9, en = 1e9; while (be <= en) { LL mid = (be + en) >> 1; if (check(mid)) be = mid + 1; else en = mid - 1; } cout << en << endl; } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif work(); return 0; }