HDU 5649 线段树+二分

来源:互联网 发布:手机淘宝怎么比价 编辑:程序博客网 时间:2024/06/05 20:44

题意:

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5649
n个数的排列,两种操作,一种将[L,R]区间内的数递减排序,另一种将[L,R]中的数递增排序,问最后第k个位置的数字是多少。


思路:

好题。
因为最后考虑的只是第k个位置的数字,二分答案。
每次将序列中比x大的都标记为1,其余包括x标记为0,每次排序前,先查询区间中有多少个1和0,然后按照操作将1和0分别更新到区间的左右两部分,用线段树区间更新区间查询即可。判断时如果第k个位置为0则r=m-1,否则l=m+1。


代码:

#include <bits/stdc++.h>using namespace std;#define lson l, m, rt << 1#define rson m + 1, r, rt << 1 | 1const int MAXN = 1e5 + 10;int n, q, k;int a[MAXN], b[MAXN], op[MAXN], LL[MAXN], RR[MAXN];int C[MAXN << 2], lazy[MAXN << 2];void pushUp(int rt) {    C[rt] = C[rt << 1] + C[rt << 1 | 1];}void pushDown(int rt, int len) {    if (lazy[rt] != -1) {        lazy[rt << 1] = lazy[rt << 1 | 1] = lazy[rt];        C[rt << 1] = (len - (len >> 1)) * lazy[rt];        C[rt << 1 | 1] = (len >> 1) * lazy[rt];        lazy[rt] = -1;    }}void build(int l, int r, int rt) {    lazy[rt] = -1;    if (l == r) {        C[rt] = a[l];        return;    }    int m = (l + r) >> 1;    build(lson);    build(rson);    pushUp(rt);}void update(int L, int R, int v, int l, int r, int rt) {    if (L <= l && r <= R) {        C[rt] = v * (r - l + 1);        lazy[rt] = v;        return;    }    pushDown(rt, r - l + 1);    int m = (l + r) >> 1;    if (L <= m) update(L, R, v, lson);    if (R > m) update(L, R, v, rson);    pushUp(rt);}int query(int L, int R, int l, int r, int rt) {    if (L <= l && r <= R) return C[rt];    pushDown(rt, r - l + 1);    int m = (l + r) >> 1, res = 0;    if (L <= m) res += query(L, R, lson);    if (R > m) res += query(L, R, rson);    return res;}int cal(int x) {    for (int i = 1; i <= n; i++) {        a[i] = (b[i] > x);    }    build(1, n, 1);    //cout << C[1] << endl;    for (int i = 1; i <= q; i++) {        int L = LL[i], R = RR[i];        int one = query(L, R, 1, n, 1);        //cout << "(" << L << ", " << R << ") one = " << one << endl;        int zero = R - L + 1 - one;        if (op[i] == 0) {            if (zero > 0) update(L, L + zero - 1, 0, 1, n, 1);            if (one > 0) update(R - one + 1, R, 1, 1, n, 1);        }        else {            if (one > 0) update(L, L + one - 1, 1, 1, n, 1);            if (zero > 0) update(R - zero + 1, R, 0, 1, n, 1);        }    }    return  (query(k, k, 1, n, 1) == 0);}void solve(int l, int r) {    int res = -1;    while (l <= r) {        int mid = (l + r) >> 1;        int tmp = cal(mid);        //cout << mid << " " << tmp << endl;        if (tmp) {            r = mid - 1;            res = mid;        }        else l = mid + 1;    }    printf("%d\n", res);}int main() {    //freopen("in.txt", "r", stdin);    int T;    scanf("%d", &T);    while (T--) {        scanf("%d%d", &n, &q);        for (int i = 1; i <= n; i++) {            scanf("%d", &b[i]);        }        for (int i = 1; i <= q; i++)            scanf("%d%d%d", &op[i], &LL[i], &RR[i]);        scanf("%d", &k);        solve(1, n);    }    return 0;}
原创粉丝点击