hdoj6703 2019 CCPCネットワークトライアル1002アレイ

問題の意味

説明

あなたは、アレイA1、A2、...、(∀i∈[1、n]は、1≤ai≤n)を与えられています。最初は、配列の各要素は、** **ユニークです。また、m個の命令があります。APOS + 10,000,000 APOSの値を変更することを示す、1(1、POS);:各命令は、次の2つの形式のいずれかであります **任意のAI(1≤i≤r)と等しくない最小値を尋ねるとすることを示す。2.(2、R、K)、** ** kより小さくありません。フォーマット2内の命令のすべての結果を印刷してください。

入力

入力の最初の行は、テストケースの数を表す整数T(1≤T≤10)を含みます。各テストケースでは、配列Aのサイズと命令の数を表す二つの整数N(1≤n≤100,000)、最初の行におけるM(1≤m≤100,000)があります。2行目で、N配列を示す異なる整数A1、A2、...、(∀i∈[1、n]は、1≤ai≤n)があります。次のmラインのために、各ラインの形式(1、T1)又は(2、T2、T3)です。各命令のパラメータは、このような方法によって生成される:フォーマット1については、我々は=t1⊕LastAnsPOSを定義しました。形式2の手順については、我々は、R =t2⊕LastAns、K =t3⊕LastAns定義(1≤pos≤nことが約束されています)。各テストケースの最初の命令の前(⊕は、ビット単位のXOR演算を意味する。)、LastAnsは、0 .Afterフォーマット2内の各命令に等しい(1≤r≤n、1≤k≤nその約束されました)LastAnsは、その命令の結果に変更されます。(Σn≤510,000、Σm≤510,000)

分析

タイトル、二つの操作の合計、一つは、一つの最小値を求めて、k番目の桁+1000,0000(1 <= I <= r)は、AIに等しくなく、数k以上です。

この数は、配列中に存在しないかもしれないことに注意してください

異なる配列の数は、従って、AI(1 <= l <=等しくないので R)、 この数に相当することができる AIに表示される(R + 1 <= iが = Nを<)。
なぜそれが可能ですか?最初の動作は+1000,10000ので、その数はどのような場合には、第1の動作を作ることになりますが繰り返されることはありません、AI(1000,0000 51,0000より大きなすぎ)。
したがって、この問題は、我々は、一度最小数kを下回らない各AI [R + 1、N]、のために、適切な変更社長木を作ることができます。
この問題のために、そうかかわらずデジタルデエンファシス(UNIQUE)、及び離散化問題のn桁の1-Nのアレイ。
上記2例に加えて、状況があり、K = N(XOR操作がされている)場合、我々は、考慮されていませんでした、そして、その答えは、n + 1ということも可能です。
要約すると、答えは3例の合計であります:

  • AI [R + 1、N](ツリーの大統領によって解決することができる)の数
  • 最初の動作は、(デジタル操作の第一セットに配置される)特定の番号を行います
  • N + 1

最小のための3つの数字、

コード

#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
int const maxn = 530000;
int const inf = 0x3f3f3f3f;
using namespace std;
int a[maxn], b[maxn];
int root[maxn << 5];//第几个版本的根节点编号
int lc[maxn << 5], rc[maxn << 5], sum[maxn << 5];
int sz;//节点个数
int n, m;

void build(int &rt, int l, int r) {
    rt = ++sz;
    if (l == r) return;
    int mid = (l + r) >> 1;
    build(lc[rt], l, mid);
    build(rc[rt], mid + 1, r);
}

int update(int id, int l, int r, int pos) {
    int _id = ++sz;
    lc[_id] = lc[id], rc[_id] = rc[id], sum[_id] = sum[id] + 1;
    if (l == r) return _id;
    int mid = (r + l) >> 1;
    if (pos <= mid)
        lc[_id] = update(lc[id], l, mid, pos);
    else
        rc[_id] = update(rc[id], mid + 1, r, pos);
    return _id;
}

//查询 不比k大的最小数字
int query(int p, int q, int l, int r, int k) {
    if (l == r) return l;
    int x1 = sum[lc[q]] - sum[lc[p]];
    int x2 = sum[rc[q]] - sum[rc[p]];
    int mid = (l + r) >> 1;
    int ans = inf;
    if (x1 > 0 && mid >= k)
        ans = query(lc[p], lc[q], l, mid, k);
    //这个if不能写为else,因为第一个if可能无法得到结果,返回inf
    if(ans == inf && x2 > 0 && r >= k)
        ans = query(rc[p], rc[q], mid + 1, r, k);
    return ans;
}


int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        while (~scanf("%d %d", &n, &m)) {
            sz = 0;
            set<int> s;
            int lastAns = 0;
            for (int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
                b[i] = a[i];
            }
            sort(b + 1, b + n + 1);
            build(root[0], 1, n);
            for (int i = 1; i <= n; i++) {
                int pos = lower_bound(b + 1, b + n + 1, a[i]) - b;
                root[i] = update(root[i - 1], 1, n, pos);
            }
            while (m--) {
                int l;
                scanf("%d", &l);
                if (l == 1) {
                    int pos = 1; // 随意初始化
                    scanf("%d", &pos);
                    pos ^= lastAns;
                    //cout << "pos = " << pos << endl;
                    s.insert(a[pos]);
                }
                else {
                    int l, k;
                    scanf("%d %d", &l, &k);
                    l ^= lastAns;
                    k ^= lastAns;
                    //cout << "l = " << l << "k = " << k << endl;
                    int ansPos = query(root[l - 1 + 1], root[n], 1, n, k);
                    lastAns = (ansPos == inf) ? inf : b[ansPos];
                    set<int>::iterator it = s.lower_bound(k);
                    //
                    if (it != s.end())  lastAns = min(lastAns, *it);
                    lastAns = min(lastAns, n + 1);
                    printf("%d\n", lastAns);
                }
            }
        }
    }
    return 0;

おすすめ

転載: www.cnblogs.com/woxiaosade/p/11422266.html