11556: 【原1556】kthxor
题目
题目描述
author: yzh119 原OJ链接:https://acm.sjtu.edu.cn/OnlineJudge-old/problem/1556
Description
给定一个数列a,数列中元素各不相同,每次可以对一个区间[l, r]进行查询,输出该区间中第2大的数与该区间所有数的异或最大值。
Input Format
第一行两个整数n,q,表示数列的长度和查询的数目。
第二行n个整数,表示这个数列。
第三行到第q+2行,每行两个整数l, r(l < r),表示需要查询的区间。
Output Format
对于所有的查询,输出给定区间中第2大的数\(x\)与该区间所有数的异或最大值: \[\max_{l \leq i \leq r}\{ a_i \textrm{ xor } x\} \]
Sample Input
3 3
1 3 2
1 2
1 3
2 3
Sample Output
2
3
1
Sample Input
11 5
892644 79740 787789 423575 534594 883691 117827 628967 504689 290297 0
2 10
7 11
3 9
6 9
6 11
Sample Output
903438
928662
903438
928662
928662
Limits
对于\(30\%\)的数据,\(n\leq 10000\)。
对于\(100\%\)的数据,\(n \leq 100000\)。
数列中所有的元素均不超过1e9。
yyong119's solution
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 3000010
using namespace std;
int n, Q, X[N], root[N];
int shu[N], num[N], top, tot;
int B[N];
int tsz, c[5000010][2], Sum[5000010], troot[100010];
int xsz, gs[N], ls[N], rs[N];
int find(int x) {
int l = 1, r = tot, mid;
while (l + 1 < r) {
mid = (l + r) >> 1;
if (num[mid] == x) return mid;
if (num[mid] < x) l = mid;
else r = mid;
}
if (num[l] == x) return l;
else return r;
}
void Insert(int &x, int y, int l, int r, int p) {
x = ++xsz;
gs[x] = gs[y] + 1;
ls[x] = ls[y]; rs[x] = rs[y];
if (l == r) return;
int mid = (l + r) >> 1;
if (p <= mid) Insert(ls[x], ls[y], l, mid, p);
else Insert(rs[x], rs[y], mid + 1, r, p);
}
int Querysecond(int a, int b) {
int L = root[a - 1], R = root[b];
int l = 1, r = tot, mid, k = 2;
while (l != r) {
mid = (l + r) >> 1;
if (gs[rs[R]] - gs[rs[L]] >= k) {
l = mid + 1; L = rs[L]; R = rs[R];
}
else {
k -= gs[rs[R]] - gs[rs[L]];
r = mid; L = ls[L]; R = ls[R];
}
}
return num[l];
}
void Trie_add(int x, int W) {
int p = troot[W - 1], now = ++tsz;
troot[W] = now;
for (int i = (1 << 30); i > 0; i >>= 1) {
Sum[now] = Sum[p] + 1;
c[now][0] = c[p][0]; c[now][1] = c[p][1];
if (x & i) {
p = c[p][1];
c[now][1] = ++tsz;
now = c[now][1];
}
else {
p = c[p][0];
c[now][0] = ++tsz;
now = c[now][0];
}
}
Sum[now] = Sum[p] + 1;
}
int Trie_query(int x, int L, int R) {
int res = 0, l = troot[L - 1], r = troot[R];
for (int i = (1 << 30); i > 0; i >>= 1) {
int p;
if (x & i) p = 0; else p = 1;
if (Sum[c[r][p]] - Sum[c[l][p]] > 0) {
res += i;
l = c[l][p]; r = c[r][p];
}
else {
l = c[l][p ^ 1]; r = c[r][p ^ 1];
}
}
return res;
}
int main() {
int l, r;
scanf("%d%d", &n, &Q);
for (int i = 1; i <= n; i++) {
scanf("%d", &X[i]);
shu[++top] = X[i];
}
sort(shu + 1, shu + 1 + top);
num[++tot] = shu[1];
for (int i = 2; i <= top; i++) if (shu[i] != shu[i - 1]) num[++tot] = shu[i];
for (int i = 1; i <= n; i++) X[i] = find(X[i]);
for (int i = 1; i <= n; i++) {
Insert(root[i], root[i - 1], 1, tot, X[i]);
Trie_add(num[X[i]], i);
}
for (int i = 1; i <= Q; i++) {
scanf("%d %d", &l, &r);
int x = Querysecond(l, r);
printf("%d\n", Trie_query(x, l, r));
}
return 0;
}