Sorted Subsegments

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;
}
原文地址:https://www.cnblogs.com/liuweimingcprogram/p/7231847.html