BZOJ 4546|CodeChef XRQRS|Xor Queries|可持久化Trie

来源:互联网 发布:爱奇艺网络直播 编辑:程序博客网 时间:2024/05/16 01:44

最全的可持久化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

101 85 1 1 11 22 2 2 72 2 2 71 14 2 2 22 1 2 34 1 3 51 6

Sample Output

822182

HINT

令N表示每次询问前数组中元素的个数

1<=L<=R<=N

1<=x<=500,000

对于第三类询问 1<=k<=N

对于第五类询问 k<=R-L+1

1<=N<=500,000

0 0
原创粉丝点击