문제의 의미
기술
만약 어레이 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;