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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值