给你一个Array{1,2...n}的数列,其中每个元素都是独立的,每个元素大小不大于1e5,长度也不大于1e5,现在有两种操作:
(1,pos):将pos位上的元素a[pos]变为a[pos]+1000000;
(2,r,k):询问当前数组中,不等于a[1],a[2]....a[r]且不小于k的元素的最小值。
因为元素数据范围不大,加上1000000就相当于删除,现在询问就变成了在[k,n+1]这个区间中寻找第一个下标大于r的,未被删除的元素。
所以可以建立权值线段树,并在权值线段树中维护下标的最大值,询问则转化为不小 于k的值里面,下标超过r的最小权值是多少。
这样,我们在查询过程中先走左子树(因为是权值线段树,左子树值更小),如果左子树中有下标大于r的就不必再走右子树了,否则一定在右子树中。这样询问就可以保证复杂度为O(nlogn)。
#include
using namespace std;
#define rep(i,l,r) for(int i=l;i<=r;++i)
#define per(i,r,l) for(int i=r;i>=l;--i)
#define pb push_back
#define mk make_pair
#define ll long long
const int inf = 1e9;
const int maxn = 1e5 + 10;
struct node {
int l, r, pos;
}t[maxn << 2];
int a[maxn], b[maxn];
int lastans, n, m, t1, cmd;
void build(int u, int l, int r) {
t[u].l = l, t[u].r = r;
if (l == r) {
t[u].pos = a[l];
return;
}
int mid = (l + r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
t[u].pos = max(t[u << 1].pos, t[u << 1 | 1].pos);
}
void update(int u, int pos) {
int l = t[u].l, r = t[u].r;
if (l == r) {
t[u].pos = n + 1;
return;
}
int mid = (l + r) >> 1;
if (pos <= mid)update(u << 1, pos);
else update(u << 1 | 1, pos);
t[u].pos = max(t[u << 1].pos, t[u << 1 | 1].pos);
}
int solve(int u, int k) {
int l = t[u].l, r = t[u].r;
if (t[u].pos < k)return inf;
if (l == r) {
return l;
}
if (t[u << 1].pos >= k)return solve(u << 1, k);
else return solve(u << 1 | 1, k);
}
int GetAns(int u, int L, int R, int k) {
int l = t[u].l, r = t[u].r;
if (l == L && r == R) {
return solve(u, k);
}
int mid = (l + r) >> 1;
if (R <= mid)return GetAns(u << 1, L, R, k);
else if (L > mid)return GetAns(u << 1 | 1, L, R, k);
else return min(GetAns(u << 1, L, mid, k), GetAns(u << 1 | 1, mid + 1, R, k));
}
signed main() {
ios::sync_with_stdio(NULL);
cin.tie(0);
int _;
cin >> _;
while (_--) {
lastans = 0;
cin >> n >> m;
rep(i, 1, n + 1)a[i] = n + 1;
rep(i, 1, n) {
cin >> b[i];
a[b[i]] = i;
}
build(1, 1, n + 1);
rep(i, 1, m) {
cin >> cmd;
if (cmd == 1) {
cin >> t1;
t1 ^= lastans;
update(1, b[t1]);
}
else {
int k, r;
cin >> r >> k;
r ^= lastans, k ^= lastans;
lastans = GetAns(1, k, n + 1, r + 1);
cout << lastans << endl;
}
}
}
return 0;
}