题目链接、
因为1操作每次加一个1e7,而k在n以内,所以1操作一下相当于把a[pos]删掉了
答案一定在内,然后建一颗权值线段树,存下标的最大值
每次2操作,相当于询问在中,下标大于的最小值是多少
查询先看左子树中是否在,左子树中最大下标是否大于
如果左子树查询完毕没有查到结果,那么看右子树是否可以查询。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5+7,inf = 0x3f3f3f3f;
int a[maxn],idx[maxn],n,m;
int Tree[maxn<<2];
void build(int l=1,int r=n+1,int x=1){
Tree[x] = idx[l];
if(l == r)return;
int mid = l+r>>1;
build(l,mid,x<<1),build(mid+1,r,x<<1|1);
Tree[x] = max(Tree[x<<1],Tree[x<<1|1]);
}
void del(int pos,int l=1,int r=n+1,int x=1){
if(l == r){
Tree[x] = inf;
return;
}
int mid = l+r>>1;
if(pos<=mid)del(pos,l,mid,x<<1);
else del(pos,mid+1,r,x<<1|1);
Tree[x] = max(Tree[x<<1],Tree[x<<1|1]);
}
int query(int k,int R,int l=1,int r=n+1,int x=1){
if(l == r)return l;
int mid = l+r>>1,ans = -1;
if(Tree[x<<1]>R && k<=mid)ans = query(k,R,l,mid,x<<1);
if(~ans)return ans;
if(Tree[x<<1|1]>R)return query(k,R,mid+1,r,x<<1|1);
return -1;
}
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]),idx[a[i]] = i;
idx[n+1] = n+1;
a[n+1] = n+1;
build();
int ans = 0;
while(m--){
int opt,t1,t2;
scanf("%d%d",&opt,&t1);
t1 ^= ans;
if(opt == 1){
del(a[t1]);
}else{
scanf("%d",&t2);
t2 ^= ans;
ans = query(t2,t1);
printf("%d\n",ans);
}
}
}
return 0;
}