[10.3模拟赛]T1

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 n\ast 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\n", q[i].ans);
	return 0;
}

可持久化\(01trie\)

posted @ 2019-11-04 19:59  Agakiss  阅读(181)  评论(0编辑  收藏  举报