[HEOI2016/TJOI2016]排序

Description

Luogu2824

BZOJ4552

Solution

这里有一个神奇的操作:01排序。如果这个序列只有0和1,那么可以查一个区间内的1的数量,然后把区间中一侧改成1,另一侧改成0就行,可以用线段树排序。

又因为询问只有一个,我们可以二分答案,然后把大于等于答案的数变成1,小于答案的数变成0。01排序后检查q上是不是1就行了。

Code

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <queue>

typedef long long ll;

const int N = 4 * 100000 + 10;

int tag[N], val[N], mid, a[N], n, m, q;
int sl[N], sr[N], st[N];

#define lson o << 1, l, mid
#define rson o << 1 | 1, mid + 1, r

void pd(int o, int l, int r) {
    int mid = (l + r) >> 1;
    if (tag[o] != -1) {
        tag[o << 1] = tag[o];
        tag[o << 1 | 1] = tag[o];
        val[o << 1] = (mid - l + 1) * tag[o];
        val[o << 1 | 1] = (r - mid) * tag[o];
        tag[o] = -1;
    }
}
void dfs(int o, int l, int r) {
    if (l == r) {
        printf("%d %d
", l, val[o]);
        return;
    }
    pd(o, l, r);
    int mid = (l + r) >> 1;
    dfs(lson);
    dfs(rson);
}
void upd(int o) { val[o] = val[o << 1] + val[o << 1 | 1]; }
void build(int o, int l, int r) {
    tag[o] = -1;
    if (l == r) {
        val[o] = (a[l] >= mid);
        return;
    }
    int mid = (l + r) >> 1;
    build(lson);
    build(rson);
    upd(o);
}
void modi(int o, int l, int r, int ql, int qr, int v) {
    if (ql <= l && r <= qr) {
        tag[o] = v;
        val[o] = v * (r - l + 1);
        return;
    }
    pd(o, l, r);
    int mid = (l + r) >> 1;
    if (ql <= mid) modi(lson, ql, qr, v);
    if (qr > mid) modi(rson, ql, qr, v);
    upd(o);
}
int query(int o, int l, int r, int ql, int qr) {
    if (ql <= l && r <= qr) {
        return val[o];
    }
    pd(o, l, r);
    int ans = 0, mid = (l + r) >> 1;
    if (ql <= mid) ans += query(lson, ql, qr);
    if (qr > mid) ans += query(rson, ql, qr);
    return ans;
}
void sort(int l, int r, int tag) {
    int x = query(1, 1, n, l, r);
    if (tag) {
        if (l <= l + x - 1) modi(1, 1, n, l, l + x - 1, 1);
        if (l + x <= r) modi(1, 1, n, l + x, r, 0);
    } else {
        if (r - x + 1 <= r) modi(1, 1, n, r - x + 1, r, 1);
        if (l <= r - x) modi(1, 1, n, l, r - x, 0);
    }
}
bool check(int x) {
    mid = x;
    build(1, 1, n);
    for (int i = 1; i <= m; ++i) {
        sort(sl[i], sr[i], st[i]);
    }
    return query(1, 1, n, q, q);
}

int main() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
    for (int i = 1; i <= m; ++i) scanf("%d%d%d", &st[i], &sl[i], &sr[i]);
    scanf("%d", &q);
    int l = 1, r = n, ans = -1;
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (check(mid)) {
            l = mid + 1;
            ans = mid;
        } else {
            r = mid - 1;
        }
    }
    printf("%d
", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/wyxwyx/p/heoi2016tjoi2016sort.html