HEOI2016/TJOI2016 排序

Posted morslin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HEOI2016/TJOI2016 排序相关的知识,希望对你有一定的参考价值。

题目传送门

奇妙的题目


把操作离线下来,二分第(q)位置上的数(x),将排列中大于(x)的数记为(1),小于(x)的数记为(0),然后就可以很简单的用线段树维护每个操作
最后判断(q)位置上的数是否为(1)
时间复杂度(O(nlog^2 n))

#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <queue>
#define LL long long
#define ls p << 1
#define rs p << 1 | 1
#define mid ((l+r) >> 1)
using namespace std;
LL read() {
    LL k = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') {
        if(c == '-') f = -1;
        c = getchar();
    }
    while(c >= '0' && c <= '9')
      k = k * 10 + c - 48, c = getchar();
    return k * f;
}
struct zzz {
    int num1, num0;
}tree[100010 << 2];
struct hhh {
    bool opt; int l, r;
}que[100010];
int tag[100010 << 2];
int n, q, pos, a[100010], b[100010];
inline void up(int p) {
    tree[p].num0 = tree[ls].num0 + tree[rs].num0;
    tree[p].num1 = tree[ls].num1 + tree[rs].num1;
}
inline void down(int p) {
    if(tag[p] != -1) {
        if(!tag[p]) {
            tree[ls].num0 = tree[ls].num0 + tree[ls].num1;
            tree[ls].num1 = 0;
            tree[rs].num0 = tree[rs].num0 + tree[rs].num1;
            tree[rs].num1 = 0;
            tag[ls] = tag[rs] = tag[p]; tag[p] = -1;
        }
        else {
            tree[ls].num1 = tree[ls].num0 + tree[ls].num1;
            tree[ls].num0 = 0;
            tree[rs].num1 = tree[rs].num0 + tree[rs].num1;
            tree[rs].num0 = 0;
            tag[ls] = tag[rs] = tag[p]; tag[p] = -1;
        }
    }
}
void build(int l = 1, int r = n, int p = 1) {
    tag[p] = -1; tree[p].num0 = tree[p].num1 = 0;
    if(l == r) {
        if(a[l]) tree[p].num1 = 1;
        else tree[p].num0 = 1;
        return ;
    }
    build(l, mid, ls); build(mid+1, r, rs);
    up(p);
}
int query(int nl, int nr, int l = 1, int r = n, int p = 1) {
    if(nl <= l && nr >= r) return tree[p].num0;
    down(p);
    int ans = 0;
    if(nl <= mid) ans += query(nl, nr, l, mid, ls);
    if(nr > mid) ans += query(nl, nr, mid+1, r, rs);
    return ans;
}
void update(int nl, int nr, bool k, int l = 1, int r = n, int p = 1) {
    if(nl <= l && nr >= r) {
        if(!k) {
            tree[p].num0 = tree[p].num0 + tree[p].num1;
            tree[p].num1 = 0; tag[p] = k;
        }
        else {
            tree[p].num1 = tree[p].num0 + tree[p].num1;
            tree[p].num0 = 0; tag[p] = k;
        }
        return ;
    }
    down(p);
    if(nl <= mid) update(nl, nr, k, l, mid, ls);
    if(nr > mid) update(nl, nr, k, mid+1, r, rs);
    up(p);
}

bool check(int k) {
    build();
    for(int i = 1; i <= q; ++i) {
        int cnt = query(que[i].l, que[i].r);
        //注意区间全部为1和全部为0的情况
        if(cnt == 0) {
            update(que[i].l, que[i].r, 1); continue;
        }
        if(cnt == que[i].r-que[i].l+1) {
            update(que[i].l, que[i].r, 0); continue;
        }
        if(que[i].opt)
            update(que[i].l, que[i].r-cnt, 1),
            update(que[i].r-cnt+1, que[i].r, 0);
        else
            update(que[i].l, que[i].l+cnt-1, 0),
            update(que[i].l+cnt, que[i].r, 1);
    }
    return !query(pos, pos);
}
int main() {
    n = read(), q = read();
    for(int i = 1; i <= n; ++i) b[i] = read();
    for(int i = 1; i <= q; ++i)
        que[i].opt = read(), que[i].l = read(), que[i].r = read();
    pos = read();
    int l = 1, r = n, ans = 0;
    while(l <= r) {
        for(int i = 1; i <= n; ++i)
            if(b[i] >= mid) a[i] = 1;
            else a[i] = 0;
        if(check(mid)) ans = mid, l = mid+1;
        else r = mid - 1;
    }
    cout << ans;
    return 0;
}

以上是关于HEOI2016/TJOI2016 排序的主要内容,如果未能解决你的问题,请参考以下文章

[HEOI2016/TJOI2016]排序 解题报告

「Luogu2824」[HEOI2016/TJOI2016]排序

[HEOI2016/TJOI2016]排序

[HEOI2016/TJOI2016]排序

HEOI2016/TJOI2016 排序

[HEOI2016/TJOI2016]排序