HDU 5649 (二分 线段树)

来源:互联网 发布:tvp动画软件 编辑:程序博客网 时间:2024/06/06 02:44

题目链接:点击这里

题意:给出一个排列,每次操作[l,r]区间的数原地升序或者降序,询问最后k下标的数。

二分最后的结果mid,然后把比mid大的换成1,小于等于mid的换成0,那么升序降序相当于求出区间中0的个数然后把前半段和后半段分别用0\1覆盖。这样只需要维护一个区间查询,区间修改的线段树即可。

#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>#include <vector>using namespace std;#define pl c<<1#define pr (c<<1)|1#define lson tree[c].l,tree[c].mid,pl#define rson tree[c].mid+1,tree[c].r,pr#define maxn 100005struct node {    int l, r, mid;    bool zero, one;///全0全1标记    int num;///0个数}tree[maxn<<3];int op[maxn][3];int a[maxn], b[maxn];int n, m, k;void build_tree (int l, int r, int c) {    tree[c].l = l, tree[c].r = r, tree[c].mid = (l+r)>>1;    tree[c].zero = tree[c].one = 0;    if (l == r) {        tree[c].num = (b[l] == 0);        return ;    }    build_tree (lson);    build_tree (rson);    tree[c].num = tree[pl].num + tree[pr].num;}void push_down (int c) {    if (tree[c].l == tree[c].r) return ;    if (tree[c].zero) {        tree[pl].zero = tree[pr].zero = 1;        tree[pl].one = tree[pr].one = 0;        tree[pl].num = tree[pl].r-tree[pl].l+1;        tree[pr].num = tree[pr].r-tree[pr].l+1;    }    else if (tree[c].one) {        tree[pl].zero = tree[pr].zero = 0;        tree[pl].one = tree[pr].one = 1;        tree[pl].num = tree[pr].num = 0;    }}void update (int l, int r, int c, int x, int y, int op) {    if (x > y) return ;    push_down (c);    if (x == l && y == r) {        if (op == 0) {            tree[c].zero = 1;            tree[c].one = 0;            tree[c].num = r-l+1;        }        else {            tree[c].zero = 0;            tree[c].one = 1;            tree[c].num = 0;        }        return ;    }    if (tree[c].mid >= y) update (lson, x, y, op);    else if (tree[c].mid < x) update (rson, x, y, op);    else {        update (lson, x, tree[c].mid, op);        update (rson, tree[c].mid+1, y, op);    }    tree[c].num = tree[pl].num+tree[pr].num;    tree[c].zero = tree[c].one = 0;}int query (int l, int r, int c, int x, int y) {    push_down (c);    if (l == x && y == r) {        return tree[c].num;    }    if (tree[c].mid >= y) {        return query (lson, x, y);    }    else if (tree[c].mid < x) {        return query (rson, x, y);    }    else {        return query (lson, x, tree[c].mid)+query (rson, tree[c].mid+1, y);    }}bool ok (int x) {    for (int i = 1; i <= n; i++) b[i] = (a[i]>x);    build_tree (1, n, 1);    for (int i = 1; i <= m; i++) { //cout << i << endl;        int tot1 = query (1, n, 1, op[i][1], op[i][2]);//0的数量        int tot2 = op[i][2]-op[i][1]+1-tot1;//1的数量        if (op[i][0] == 1) {            update (1, n, 1, op[i][1], op[i][1]+tot2-1, 1);            update (1, n, 1, op[i][2]-tot1+1, op[i][2], 0);        }        else {            update (1, n, 1, op[i][1], op[i][1]+tot1-1, 0);            update (1, n, 1, op[i][2]-tot2+1, op[i][2], 1);        }    }    int res = query (1, n, 1, k, k);    return res^1;}int main () {    //freopen ("more.in", "r", stdin);    int t;    scanf ("%d", &t);    while (t--) {        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", &op[i][0], &op[i][1], &op[i][2]);        scanf ("%d", &k);        int l = 1, r = n;        while (r-l > 1) {            int mid = (l+r)>>1;            if (ok (mid)) l = mid;            else r = mid;        }        printf ("%d\n", ok (l) ? r : l);    }    return 0;}
0 0