hdoj6703 2,019 CCPC 네트워크 시험 1,002 어레이

문제의 의미

기술

만약 어레이 A1을 주어, A2, ..., (∀i∈ [1, N] 1≤ai≤n). 처음에는 배열의 각 요소는 ** 독특한 **입니다. 또한, m의 지시가있다. APOS + 10,000,000 APOS 값을 변경 나타내는 1 (1, POS), 각 명령은 다음과 같은 두 가지 형식의 하나 인 ** 모든 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)가있다. 두번째 라인에서, n은 어레이를 나타내는 다른 정수의 A1, A2, ..., (∀i∈ [1, N] 1≤ai≤n)이있다. 다음의 m 라인의 경우, 각 라인은 포맷 (1 T1) 또는 (2, T2, T3)이다. 각 명령의 매개 변수는에 의해 생성된다 : 식 1의 지시를 위해, 우리는 POS = t1⊕LastAns 정의. 포맷 2에 대한 지침 (이것은 1≤pos≤n 약속한다), 우리는 R = t2⊕LastAns, K = t3⊕LastAns 정의. 각 테스트 케이스의 마지막 명령어 (즉 ⊕는 비트 단위 XOR 연산자를 의미합니다.) LastAns 포맷 2 0 후론 각각의 명령과 동일하다 (1≤r≤n, 1≤k≤n 것을 약속) LastAns 그 명령어의 결과로 변화한다. (Σn≤510,000, Σm≤510,000)

분석

제목, 두 동작의 총합, 하나 하나가 최소 찾고, k 번째 자릿수 +1000,0000 (1 <= I <= R) AI와 같지 않은, 상기 수 k 이상인.

이 숫자 어레이에 존재하지 않을 수 있음을 유의

다른 배열의 수, 따라서, AI (1 <= I <= 동일하지 않기 때문에 , R) 이 숫자와 같은 는 AI에 표시 (R + 1 <= i가 = N을 <).
왜이 가능? 제 1 동작 때문에 +1000,10000 때문에, 그 수는 어떤 경우에, 첫 번째 작업을하게 될 것이다 반복되지 않을 것이다 인공 지능 (1000,0000 51,0000보다 더 큰 너무 많이).
따라서,이 문제는, 우리는 최소의 K보다 작지 적절히 변경 회씩 AI 대통령 트리 [R + 1, N]을 만들 수있다.
이 문제 때문에, 그래서 상관없이 디지털 디엠 (UNIQUE)의 N 자리수의 1-N, 및 이산화 문제 어레이.
K = N (XOR 동작이 됨) 경우 위의 두 건으로 또한, 상황이, 우리는 다음 응답이 가능하다 또한, 고려되지 않았던 N + 1.
요약하면, 대답은 세 가지 경우 총입니다 :

  • AI [R + 1, N] (트리 회장에 의해 해결 될 수 있음) 다수의
  • 제 1 동작은 (디지털 동작의 제 1 세트에 배치된다) 특정 수의 실시
  • N + 1

에 최소 세 가지 수치,

코드

#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