题目链接:https://vjudge.net/problem/HDU-6703
题解:因为每次加1e7,k也只有[1, n],所以结果也就是[1, n + 1],所以对于加了1e7的数我们set记录一下原先的值,对于每次查询,我们输出set中第一个大于等于k的 和原序列 [r + 1, n] 大于等于k的最小值 中较小的即可,那么问题就是用主席树找到第一个大于等于k的数了,这种方式也是第一次写,看代码吧
#include
using namespace std;
const int N = 1e5 + 10;
struct node {
int l, r;
int val;
}tree[N * 22];
int n, m;
int a[N];
int root[N], tot;
set ss;
int update(int pre, int l, int r, int pos) {
int cur = ++tot;
tree[cur] = tree[pre];
tree[cur].val++;
if(l == r) return cur;
int mid =(l + r) >> 1;
if(pos <= mid) tree[cur].l = update(tree[pre].l, l, mid, pos);
else tree[cur].r = update(tree[pre].r, mid + 1, r, pos);
return cur;
}
int query(int pl, int pr, int l, int r, int pos) {
if(l == r) {
return l;
}
int res = N;
int mid = (l + r) >> 1;
if(pos >= l) {
if(pos <= mid && tree[tree[pr].l].val - tree[tree[pl].l].val > 0) res = min(res, query(tree[pl].l, tree[pr].l, l, mid, pos));
if(tree[tree[pr].r].val - tree[tree[pl].r].val > 0)res = min(res, query(tree[pl].r, tree[pr].r, mid + 1, r, pos));
} else {
if(tree[tree[pr].l].val- tree[tree[pl].l].val > 0) res = min(res, query(tree[pl].l, tree[pr].l, l, mid, pos));
else if(tree[tree[pr].r].val - tree[tree[pl].r].val > 0)res = min(res, query(tree[pl].r, tree[pr].r, mid + 1, r, pos));
}
return res;
}
int queryrk(int rr, int k) {
// cout << rr << " -- " << k << endl;
if(rr > n) return n + 1;
int num = 0;
num = query(root[rr - 1], root[n], 1, n, k );
// cout << num << endl;
if(num > n) num = n + 1;
return num;
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
tot = 0;
ss.clear();
scanf("%d %d", &n, &m);
for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
for(int i = 1; i <= n; i++) {
root[i] = update(root[i - 1], 1, n, a[i]);
}
ss.insert(n+1);
int ans=0,op,r,k,ans1,ans2;
while(m--){
scanf("%d%d",&op,&r);
// printf("%d ",r);
r^=ans;
if(op==1) ss.insert(a[r]);
else{
scanf("%d",&k);
k^=ans;
ans1=queryrk(r+1,k);
ans2=*ss.lower_bound(k);
ans=min(ans1,ans2);
printf("%d\n",ans);
}
}
}
return 0;
}