​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\n", 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;
}