問題の意味
長さの順列N A、\(で\ FORALL I \ [1、N] ,. 1 \ルa_iを\ルN \)、M操作、各操作:
- (1、POS)、\(A_ {POSは} \)となる\(A_ {POS} + 10000000 \)
- (2は、R、k)は、その結果、xの最小値を見つけるために、\(\ iは[IN \ FORALL 1、R]、X \ NEQ a_iを、X \ GE K \)
データ範囲:
\(1 \ n \ mの100000.1 \ 100000.1 \ Rを\ n、1つの\ k個の\ N \ \)
分析
各数値範囲がで、観察された([1、N-] \)\ k個の範囲の間、また、(\ [N-、1])\それが最終的な答えではだろう、との間の(\ [1 )N + 1] \の間です。
図1は、デジタル動作する\(a_iを\)を加えた1E7を、それが表すように、これは、はるかに、nとkの数を超えている\(a_iを\)を元の配列から削除されています。
それぞれクエリに最初、唯一の答えによって知ることができる[K、N + 1]、配列中のみに番号[1、N-(1つの施し削除操作、無考慮) 。だから我々は、すべてのクエリシーケンスが表示されないことができます\([K、N] \ ) 番号、およびRよりも大きいの彼らのインデックス。以前に削除されたり番号場合\(X \)のためのように、次に置く率nは、それよりも大きくなる\(K \ルX \)場合、\(X \)はインデックスに対応していますそれはより大きい\(R&LT \)(候補xとして、すなわち、回答)
どのように必要なものをクエリ維持するには?最大重量指数の重量セグメントツリーのメンテナンス間隔
- 動作のために、直接、単一の点から1 + N添字なります
- 動作2については、区間[K、n]は、戻りノードが含むの最大屈折率は、ノードを残している場合、これらのノードのために、R、次いで再帰左ノードよりも大きい、またはしない場合、右のノードを表示することであることがN + 1(回答候補の代わりには、n + 1です)。したがって、それはそうでなければ、1 N +単一点の重みを返す場合、再帰の終了が、インデックスのメンテナンスの単一の点をrよりも大きいかどうかを確認します。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+10;
const int inf = 0x3f3f3f3f;
int a[N],b[N];
struct SegTree{
int l,r,id;
}t[4*N];
int n,m;
void build(int p,int l,int r){
t[p].l = l;t[p].r = r;
if(l == r){
t[p].id = b[l];
return;
}
int mid = l + r >> 1;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
t[p].id = max(t[p*2].id,t[p*2+1].id);
}
void change(int p,int x){
if(t[p].l == t[p].r && t[p].l == x){
t[p].id = n+1;return;//删除该数,将维护的下标变为n+1
}
int mid = t[p].l + t[p].r >> 1;
if(x <= mid)change(p*2,x);
else if(x > mid)change(p*2+1,x);
t[p].id = max(t[p*2].id,t[p*2+1].id);
}
int query(int p,int l,int r,int x){
if(t[p].l >= l && t[p].r <= r){//找到被[k,n]完全包含的结点
if(t[p].l == t[p].r){
if(t[p].id > x)
return t[p].l;
return n + 1;
}
if(t[p*2].id > x)return query(p*2,l,r,x);
if(t[p*2+1].id > x)return query(p*2+1,l,r,x);
return n + 1;
}
int mid = t[p].l + t[p].r >> 1;
int res = n+1;
if(mid >= l){
res = query(p*2,l,r,x);
}
if(mid < r){
res = min(res, query(p*2+1,l,r,x));
}
return res;
}
int main(){
int T;scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)b[i] = 0;
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[a[i]] = i;//因为时排列,每个a[i]都不一样
}
build(1,1,n);
int res = 0;
while(m--){
int op,x,y;
scanf("%d%d",&op,&x);
if(op == 1){
x ^= res;
change(1,a[x]);
}
else{
scanf("%d",&y);x^=res;y^=res;
res = query(1,y,n,x);
printf("%d\n",res);
}
}
}
return 0;
}