最全的可持久化Trie新手入门题,没有之一(误)。
为什么我的那么慢啊?
为什么你们这么熟练啊?
MLE了3次。。我真是傻逼。
最大化异或和参见:
http://blog.csdn.net/huanghongxun/article/details/50429416
#include <cstdio>
const int N = 500005;
struct Trie {
Trie* c[2]; int size;
Trie() { c[0] = c[1] = this; size = 0; }
Trie(Trie *l, Trie *r, int sz) { c[0] = l, c[1] = r, size = sz; }
void* operator new(size_t);
Trie* put(int x, int digit = 1 << 18) {
if (!digit)
return new Trie(c[0], c[1], size + 1);
if (x & digit)
return new Trie(c[0], c[1]->put(x, digit >> 1), size + 1);
else
return new Trie(c[0]->put(x, digit >> 1), c[1], size + 1);
}
static int get(Trie *p1, Trie *p2, int x, int digit = 1 << 18) {
if (!digit)
return 0;
int t = bool(~x & digit);
if (p1->c[t]->size - p2->c[t]->size)
return (~x & digit) | get(p1->c[t], p2->c[t], x, digit >> 1);
else
return (x & digit) | get(p1->c[t ^ 1], p2->c[t ^ 1], x, digit >> 1);
}
static int kth(Trie *p1, Trie *p2, int k, int digit = 1 << 18) {
if (!digit) return 0;
int t = p1->c[0]->size - p2->c[0]->size;
if (k <= t) return kth(p1->c[0], p2->c[0], k, digit >> 1);
else return digit | kth(p1->c[1], p2->c[1], k - t, digit >> 1);
}
static int less(Trie *p1, Trie *p2, int x, int digit = 1 << 18) {
if (!digit) return p1->size - p2->size;
int sz = p1->c[0]->size - p2->c[0]->size, ans = 0, t = bool(x & digit);
if (t) ans += sz;
return ans + less(p1->c[t], p2->c[t], x, digit >> 1);
}
} *trie[N];
Trie pool[N * 20], *C = pool;
void *Trie::operator new(size_t) { return C++; }
int main() {
int t, op, l, r, x, tot = 0;
scanf("%d", &t);
trie[0] = new Trie();
while (t--) {
scanf("%d", &op);
switch(op) {
case 1:
scanf("%d", &x); ++tot;
trie[tot] = trie[tot - 1]->put(x);
break;
case 2:
scanf("%d%d%d", &l, &r, &x);
printf("%d\n", Trie::get(trie[r], trie[l - 1], x));
break;
case 3:
scanf("%d", &x); tot -= x; C = trie[tot + 1] - 1;
break;
case 4:
scanf("%d%d%d", &l, &r, &x);
printf("%d\n", Trie::less(trie[r], trie[l - 1], x));
break;
case 5:
scanf("%d%d%d", &l, &r, &x);
printf("%d\n", Trie::kth(trie[r], trie[l - 1], x));
break;
}
}
return 0;
}
4546: codechef XRQRS
Description
给定一个初始时为空的整数序列(元素由1开始标号)以及一些询问:
类型1:在数组后面就加入数字x。
类型2:在区间L…R中找到y,最大化(x xor y)。
类型3:删除数组最后K个元素。
类型4:在区间L…R中,统计小于等于x的元素个数。
类型5:在区间L…R中,找到第k小的数。
Input
输入数据第一行为一个整数q,表示询问个数,接下来q行,每行一条询问 对应题目描述。
类型1的询问格式为“1 x”。
类型2的询问格式为“2 L R x”。
类型3的询问格式为“3 k”。
类型4的询问格式为“4 L R x”。
类型5的询问格式为“5 L R k”。
Output
对于每个2、4、5询问输出一行对应答案
Sample Input
10
1 8
5 1 1 1
1 2
2 2 2 7
2 2 2 7
1 1
4 2 2 2
2 1 2 3
4 1 3 5
1 6
Sample Output
8
2
2
1
8
2
HINT
令N表示每次询问前数组中元素的个数
1<=L<=R<=N
1<=x<=500,000
对于第三类询问 1<=k<=N
对于第五类询问 k<=R-L+1
1<=N<=500,000