D2. 388535 (Hard Version)

这里直接上 D2D2D2 的做法吧。我们可以知道 l⊕xl\oplus xl⊕x 一定在 aaa 中,所以对于 (a[i]⊕l)(a[i]\oplus l)(a[i]⊕l) (1<=i<=r-l+1) ,总有一个是 xxx 。我们现在设 b[i]=(a[i]⊕l)b[i]=(a[i]\oplus l)b[i]=(a[i]⊕l) ,那么我们怎么判断 b[i]b[i]b[i] 是不是 xxx 呢?首先我们要知道原序列是一个排列,所以不会有相同的数字,且当前序列是通过原序列异或上同一个数字得到的,所以当前序列也不会有相同的数字,所以当前的序列再异或上一个相同的数字也不可能有相同的数字。
那么想要知道 b[i]b[i]b[i] 是否可以作为 xxx ,我们只要知道:
min{b[i]⊕a[j]∣1≤j≤r−l+1}==l ?
min\{b[i]\oplus a[j]\mid 1\leq j\leq r-l+1\} ==l\ ?
min{b[i]⊕a[j]∣1≤j≤r−l+1}==l ? 和
max{b[i]⊕a[j]∣1≤j≤r−l+1}==r ?
max\{b[i]\oplus a[j]\mid 1\leq j\leq r-l+1\}==r\ ?
max{b[i]⊕a[j]∣1≤j≤r−l+1}==r ?
因为如果最小值为 lll ,最大值为 rrr ,且我们知道每个数都不同,那不自然就是 [l,r][l,r][l,r] 的一个排列了么。求上述最小值和最大值就是经典的 010101 字典树问题了。
#include<bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
int a[N];
int tot, nxt[20*N][2];
void clear() {
tot = 0;
nxt[0][0] = nxt[0][1] = 0;
}
void insert(int x) {
int rt = 0;
for (int i = 20; i >= 0; --i) {
int cur = (x >> i & 1);
if (!nxt[rt][cur]) {
nxt[rt][cur] = ++tot;
nxt[tot][0] = nxt[tot][1] = 0;
}
rt = nxt[rt][cur];
}
}
int query_min(int x) {
int rt = 0, ans = 0;
for (int i = 20; i >= 0; -- i) {
int cur = (x >> i & 1);
int need = cur;
if (!nxt[rt][need]) {
ans = (ans << 1) | 1;
need = !need;
}
else {
ans = (ans << 1);
}
rt = nxt[rt][need];
}
return ans;
}
int query_max(int x) {
int rt = 0, ans = 0;
for (int i = 20; i >= 0; -- i) {
int cur = (x >> i & 1);
int need = (cur ^ 1);
if (!nxt[rt][need]) {
ans = (ans << 1);
need = !need;
}
else {
ans = (ans << 1) | 1;
}
rt = nxt[rt][need];
}
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T; scanf("%d", &T);
int n;
while(T--) {
int l, r; scanf("%d%d", &l, &r);
for (int i = l; i <= r; ++i) {
scanf("%d", &a[i]);
insert(a[i]);
}
int x;
for (int i = l; i <= r; ++i) {
if (query_min(a[i] ^ l) == l && query_max(a[i] ^ l) == r) {
x = (a[i] ^ l);
break;
}
}
clear();
printf("%d\n", x);
// for (int i = l; i <= r; ++i) {
// cout << (x ^ a[i]) << ' ';
// }
// cout << endl << endl;
}
}

本文介绍了一种解决D2.388535(HardVersion)问题的方法,利用01字典树来判断序列是否为指定范围内的全排列。通过对原序列进行特定操作,可以高效地确定序列的有效性。
1294

被折叠的 条评论
为什么被折叠?



