码迷,mamicode.com
首页 > 编程语言 > 详细

HEOI2016/TJOI2016 排序

时间:2019-11-14 11:21:27      阅读:70      评论:0      收藏:0      [点我收藏+]

标签:位置   时间复杂度   ref   read   mes   efi   include   using   algo   

题目传送门

奇妙的题目


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

标签:位置   时间复杂度   ref   read   mes   efi   include   using   algo   

原文地址:https://www.cnblogs.com/morslin/p/11855715.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!