HDU 6703 array(主席树)

题意
给定一个长度为n的排列(1-n),要你实现操作两种,

1 x:给第x个数加上1e7;

2 x y:查询最小的且不小于y的且不在区间[1,x]里出现过的数。

题解
对权值建主席树,维护区间最小值,插入一个数相当于这个数被ban,进行1操作相当于取消ban,如果真去实现修改会比较麻烦,由于这个序列是一个排列,我们对一些数取消ban相当于答案可以直接出现在这些数里,所以我们可以用set保存一下取消ban的数然后联合查询即可。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<stack>
#include<cstdlib>
#include<queue>
#include<set>
#include<string.h>
#include<vector>
#include<deque>
#include<map>
using namespace std;
#define INF 0x3f3f3f3f3f3f3f3f
#define inf 0x3f3f3f3f
#define eps 1e-4
#define bug printf("*********\n")
#define debug(x) cout<<#x"=["<<x<<"]" <<endl

#define Mod(a,b) a<b?a:a%b+b
typedef long long LL;
typedef long long ll;
const int maxn = 1e5 + 5;
#define ls lson
#define rs rson
#define up update
#define qu query
int a[maxn],root[maxn],minv[maxn * 20],lson[maxn * 20],rson[maxn * 20];
int cnt,tot;

void build(int &o, int l, int r) {  
    o = ++tot;
    if (l == r) {
        minv[o] = l;
        return;
    }
    int mid = (l + r) >> 1;
    build(lson[o], l, mid);
    build(rson[o], mid + 1, r);
    minv[o] = min(minv[lson[o]], minv[rson[o]]);
}
void update(int &o, int pre, int l, int r, int p) {
    o = ++cnt;
    lson[o] = lson[pre];
    rson[o] = rson[pre];
    if (l == r) {
        minv[o] = 1e9;
        return;
    }
    int mid = (l + r) >> 1;
    if (p <= mid) update(lson[o], lson[pre], l, mid, p);
    else update(rson[o], rson[pre], mid + 1, r, p);
    minv[o] = min(minv[lson[o]],minv[rson[o]]);
}
int query(int o, int l, int r, int ql, int qr){
    if(l >= ql && r <= qr) return minv[o];
    int mid = (l + r) >> 1;
    int res = 1e9;
    if(ql <= mid) res = min(res,query(lson[o], l, mid, ql, qr));
    if(qr > mid) res = min(res,query(rson[o],mid + 1, r, ql, qr));
    return res;
}

set<int>s;
int h = 1e5 + 1;
int main() {
    int T;
    scanf("%d", &T);
    build(root[0], 1, h);
    while (T--) {
        cnt = tot;
        s.clear();
        int n, q;
        scanf("%d %d", &n, &q);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            update(root[i], root[i - 1], 1, h, a[i]);
        }
        int lastans = 0;
        int id, x, y;
        while (q--) {
            scanf("%d", &id);
            if (id == 1) {
                scanf("%d", &x);
                x ^= lastans;
                s.insert(a[x]);
            } else {
                scanf("%d %d", &x, &y);
                x ^= lastans;
                y ^= lastans;
                int res1 = query(root[x], 1, h, y, h);
                int res2 = 1e9;
                auto it = s.lower_bound(y);
                if(it != s.end()) res2 = *it;
                lastans = min(res1,res2);
                printf("%d\n",lastans);
            }
        }
    }
}
View Code

 

posted @ 2019-09-02 21:07  千摆渡Qbd  阅读(174)  评论(0)    收藏  举报