天天看点

2019CCPC网络赛——array(权值线段树)2019CCPC网络赛——array(权值线段树)

2019CCPC网络赛——array(权值线段树)

题目地址

题意

两种操作

1. 给 a[i] + 10000000

2. 查找不存在 在a[1 ~ r] 中 且不低于k的数

思路

在第一个操作时 由于k的范围不够 就相当于把 a[i] 删除掉即a[i]的下标变为无穷大而对于第二种操作 也就是 等价为在 k之后 的下标的大于r 的可以使用权值线段树用来维护当前区间最大的 下标如果当前的右端点 大于等于k 且 且最大下标大于 r 那就可以在这个区间中查找但是不一定这个区间存在 因为也有可能是 在 小于k的那段而且 下标是 由低到高 所以 能左边 最好左边最好 返回的不是该点的下标 而是这个点所以 也就是这个l,r

代码

#include<iostream>

using namespace std;
const int N = 1e5+10,INF = 0x3f3f3f3f;
struct Node{
    int l,r;
    int maxp;
}tr[N * 4];
int a[N],id[N];
int n,m;
void pushup(int u){
    tr[u].maxp = max(tr[u<<1].maxp,tr[u<<1|1].maxp);
}
void build(int u,int l,int r){
    tr[u] = {l,r};
    if(l == r){
        tr[u].maxp = id[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(u<<1,l,mid);
    build(u<<1|1,mid + 1,r);
    pushup(u);
}
void modify(int u,int k){
    if(tr[u].l == tr[u].r){
        tr[u].maxp = INF;
        return;
    }
    int mid = (tr[u].l + tr[u].r) >> 1;
    if(k <= mid) modify(u<<1,k);
    else modify(u<<1|1,k);
    pushup(u);
}
int query(int u,int k,int r){
    if(tr[u].l == tr[u].r){
        if(tr[u].maxp > r)
            return tr[u].l;
        else return -1;
    }
    int ans = -1;
    int mid = (tr[u].r + tr[u].l) >> 1;
    if(k <= mid && tr[u<<1].maxp > r)
        ans = query(u<<1,k,r);
    if(ans != -1) return ans;
    if(tr[u<<1|1].r>=k&&tr[u<<1|1].maxp > r)
        ans = query(u<<1|1,k,r);
    return ans;
}
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i = 1;i<=n;i++){
            scanf("%d",&a[i]);
            id[a[i]] = i;
        }
        build(1,1,n);
        int ans = 0;
        while(m--){
            int op;
            scanf("%d",&op);
            if(op == 1){
                int x;
                scanf("%d",&x);
                x ^= ans;
                modify(1,a[x]);
            }
            else{
                int k,r;
                scanf("%d%d",&r,&k);
                k ^= ans,r ^= ans;
                ans = query(1,k,r);
                if(ans == -1)
                    ans = max(n + 1,k);
                printf("%d\n",ans);
            }
        }
    }
    
    return 0;
}