题意:
给定一个长为 n 的排列,然后给出 m 个操作,① (1, pos),表示 a[pos] 加上 1000w;② (2, r, k),询问大于等于 k 的最小的不在 a[1] … a[r] 中出现的数,强制在线。(n, m <= 1e5)
链接:
https://cn.vjudge.net/problem/HDU-6703
题解:
注意到进行过修改操作后的数不可能成为询问的答案,答案最大为 n + 1,则修改操作对应为删除操作。考虑建立权值线段树,每个结点存放对应下标,则询问转化为在区间 [k, n + 1] 中找到第一个下标大于 r 的值。线段树维护区间最值,删除操作对应把下标赋0,查询时候定位到相应区间后,再判断是否继续进行单点查询,详见代码。
参考代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
#define pb push_back
#define sz(a) ((int)a.size())
#define mem(a, b) memset(a, b, sizeof a)
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define gmid (l + r >> 1)
#define lnum (mid - l + 1)
#define rnum (r - mid)
const int maxn = 1e5 + 5;
const int maxm = 2e5 + 5;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
int a[maxn], mx[maxn << 2];
int n, m;
void build(int l, int r, int rt){
if(l == r) { mx[rt] = a[l]; return; }
int mid = gmid;
build(l, mid, lson);
build(mid + 1, r, rson);
mx[rt] = max(mx[lson], mx[rson]);
}
void update(int l, int r, int rt, int pos, int val){
if(l == r) { mx[rt] = val; return; }
int mid = gmid;
if(pos <= mid) update(l, mid, lson, pos, val);
else update(mid + 1, r, rson, pos, val);
mx[rt] = max(mx[lson], mx[rson]);
}
int dfs(int l, int r, int rt, int val){
if(l == r) return l;
int mid = gmid;
if(mx[lson] > val) return dfs(l, mid, lson, val);
else return dfs(mid + 1, r, rson, val);
}
int query(int l, int r, int rt, int L, int R, int val){
if(l >= L && r <= R){
if(mx[rt] <= val) return 0;
return dfs(l, r, rt, val);
}
int mid = gmid;
if(L <= mid) if(int ret = query(l, mid, lson, L, R, val)) return ret;
if(R > mid) if(int ret = query(mid + 1, r, rson, L, R, val)) return ret;
return 0;
}
int main() {
// ios::sync_with_stdio(0); cin.tie(0);
int t; scanf("%d", &t);
while(t--){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i) scanf("%d", &a[i]);
++n; a[n] = n; build(1, n, 1);
for(int i = 1; i <= n; ++i) update(1, n, 1, a[i], i);
int ret = 0;
while(m--){
int opt, x, y; scanf("%d%d", &opt, &x);
if(opt == 1){
x ^= ret;
if(!a[x]) continue;
update(1, n, 1, a[x], n);
a[x] = 0;
}
else{
scanf("%d", &y);
x ^= ret, y ^= ret;
ret = query(1, n, 1, y, n, x);
printf("%d\n", ret);
}
}
}
return 0;
}