HDU-6703配列(セグメントツリー)

問題の意味

長さの順列N A、\(で\ FORALL I \ [1、N] ,. 1 \ルa_iを\ルN \)、M操作、各操作:

  1. (1、POS)、\(A_ {POSは} \)となる\(A_ {POS} + 10000000 \)
  2. (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. 各数値範囲がで、観察された([1、N-] \)\ k個の範囲の間、また、(\ [N-、1])\それが最終的な答えではだろう、との間の(\ [1 )N + 1] \の間です。

  2. 図1は、デジタル動作する\(a_iを\)を加えた1E7を、それが表すように、これは、はるかに、nとkの数を超えている\(a_iを\)を元の配列から削除されています。

  3. それぞれクエリに最初、唯一の答えによって知ることができる[K、N + 1]、配列中のみに番号[1、N-(1つの施し削除操作、無考慮) 。だから我々は、すべてのクエリシーケンスが表示されないことができます\([K、N] \ ) 番号、およびRよりも大きいの彼らのインデックス。以前に削除されたり番号場合\(X \)のためのように、次に置く率nは、それよりも大きくなる\(K \ルX \)場合、\(X \)はインデックスに対応していますそれはより大きい\(R&LT \)候補xとして、すなわち、回答)

どのように必要なものをクエリ維持するには?最大重量指数の重量セグメントツリーのメンテナンス間隔

  1. 動作のために、直接、単一の点から1 + N添字なります
  2. 動作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;
}

おすすめ

転載: www.cnblogs.com/1625--H/p/11404011.html