Description
(Jim)是一个热爱打游戏的小伙子,可惜他的游戏水平不太行,以至于经常在游戏里被别人欺负。
而且(Jim)不仅游戏玩的菜,他还很爱喷人,但是由于自己的垃圾操作,他又喷不过别人。
为了改善这种局面,(Jim)决定成为一个腿部挂件(俗称抱大腿)。
已知现在有(N)个选手可供Jim选择,每位选手的能力值为(ai)。
(N)位选手不一定每位选手都有时间配(Jim)玩游戏而且(Jim)的状态也时好时坏,所以(Jim)有(Q)个询问,每个询问是(3)个数(X)、(L)、(R),求第(L)个人到第(R)个人这(R-L+1)个人中与(Jim)配合后的能力值最大是多少,(Jim)与第i位选手配合后的能力值为(ai)与(X)进行异或运算((Xor))。
Input
第(1)行:(2)个数(N),(Q)中间用空格分隔,分别表示选手个数及查询的数量((1≤N≤200000,1≤Q≤200000))。
第(2)行:共N个数为每个选手能力值中间用空格分隔,对应(ai(0≤a[i]≤10^9))。
第(N+2-N+Q+1)行:每行(3)个数(X,L,R),中间用空格分隔。((0≤X≤10^9,0≤L≤R<N))。
Output
输出共(Q)行,对应每次询问所能得到的最大能力值。
Sample Input
9 8
2 15 4 12 0 6 0 16 12
2 2 5
4 8 8
16 5 8
16 6 8
1 0 5
12 3 4
15 1 1
5 0 4
Sample Output
14
8
28
28
14
12
0
10
Data Constraint
对于 (20\%) 的数据保证((1 leq N leq 5000,1 leq Q leq 5000))。
对于 (45\%) 的数据保证((1 leq N leq 50000,1 leq Q leq 50000))。
对于 (100\%) 的数据保证((1 leq N leq 200000,1 leq Q leq 200000))。
Limit
(2000)ms 256M
Solution
考场上脑子坏了,只写出了(n^{0.5}ast nast logn),用莫队维护当前的区间,保证只有区间的内的数在(01tire)上。
看完题解才知道自己写过差不多的原题,真的是失了智。
老套路,用可持久(01trie)维护节点,用(pre)维护区间就行了
Code
上一下考场代码
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define M 30
#define MAXN 5000000
int n, m, BASE, x, l, r, cnt;
int a[MAXN], tot[MAXN], trie[MAXN][2];
struct rec {
int x, l, r, base, num, ans;
} q[MAXN];
inline int read() {
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
inline bool cmp1(rec x, rec y) {
return x.base == y.base ? x.r < y.r : x.base < y.base;
}
inline bool cmp2(rec x, rec y) {
return x.num < y.num;
}
inline void Add(int x) {
int now = 0;
for (register int i = M; i >= 1; i--) {
int h = x & (1 << (i - 1)); if (h) h = 1;
if (!trie[now][h]) ++cnt, trie[now][h] = cnt;
now = trie[now][h];
tot[now]++;
}
}
inline void Delete(int x) {
int now = 0;
for (register int i = M; i >= 1; i--) {
int h = x & (1 << (i - 1)); if (h) h = 1;
now = trie[now][h];
tot[now]--;
}
}
inline int Query(int x) {
int now = 0, ans = 0;
for (register int i = M; i >= 1; i--) {
int h = x & (1 << (i - 1)); if (h) h = 1;
if (tot[trie[now][!h]])
ans += (!h) * 1 << (i - 1), now = trie[now][!h];
else
ans += h * 1 << (i - 1), now = trie[now][h];
}
return ans;
}
int main() {
n = read(), m = read();
BASE = sqrt(n);
for (register int i = 1; i <= n; i++)
a[i] = read();
for (register int i = 1; i <= m; i++)
q[i].x = read(), q[i].l = read() + 1, q[i].r = read() + 1, q[i].base = q[i].l / BASE, q[i].num = i;
sort(q + 1, q + m + 1, cmp1);
l = 1, r = 1, Add(a[1]);
for (register int i = 1; i <= m; i++) {
while (r < q[i].r) { r++; Add(a[r]); }
while (r > q[i].r) { Delete(a[r]); r--; }
while (l < q[i].l) { Delete(a[l]); l++; }
while (l > q[i].l) { l--; Add(a[l]); }
q[i].ans = Query(q[i].x) ^ q[i].x;
}
sort(q + 1, q + m + 1, cmp2);
for (register int i = 1; i <= m; i++)
printf("%d
", q[i].ans);
return 0;
}
可持久化(01trie)