bzoj 4546: codechef XRQRS [可持久化Trie]

Candy?發表於2017-05-05

4546: codechef XRQRS


可持久化Trie

codechef上過了,bzoj上蜜汁re,看別人說要開5.2e5才行。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int N = 5.2e5+5;
inline int read() {
    char c=getchar(); int x=0,f=1;
    while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*f;
}

void put(int x) {
    for(int i=19; i>=0; i--) {
        if(x & (1<<i)) putchar('1'); 
        else putchar('0');
    }
    printf("    %d\n", x);
}
int Q, op, l, r;
int tot;
namespace trie {
#define ch(x, f) t[x].ch[f]
    struct node {int ch[2], size;} t[N * 20];
    int sz, root[N];
    void insert(int &x, int p, int val) { //printf("insert %d  %d\n", val, bool(val & (1<<p)));
        t[++sz] = t[x]; x = sz;
        t[x].size ++;
        if(p < 0) return;
        if(val & (1<<p)) insert(t[x].ch[1], p-1, val);
        else insert(t[x].ch[0], p-1, val);
    }

    int max_xor(int x, int y, int p, int val) {
        int ans = 0;
        while(p >= 0) {
            bool f = ~ val & (1<<p); 
            if(t[ch(y, f)].size - t[ch(x, f)].size == 0)  f ^= 1;
            x = t[x].ch[f], y = t[y].ch[f]; 
            if(f) ans |= (1<<p);
            p--;
        }
        return ans;
    }

    int small(int x, int y, int p, int val) {
        int ans = 0;
        while(p >= 0) {
            bool f = val & (1<<p);
            if(f) ans += t[ch(y, 0)].size - t[ch(x, 0)].size;
            y = ch(y, f), x = ch(x, f);
            p--;
        }
        ans += t[y].size - t[x].size;
        return ans;
    }

    int kth(int x, int y, int p, int k) {
        int ans = 0, lsize = 0;
        while(p >= 0) {
            int _ = lsize + t[ch(y, 0)].size - t[ch(x, 0)].size;
            if(k <= _) y = ch(y, 0), x = ch(x, 0);
            else lsize = _, ans |= (1<<p), y = ch(y, 1), x = ch(x, 1);
            p--;
        }
        return ans;
    }
} using trie::root;

void add(int x) {
    tot++;
    root[tot] = root[tot-1];
    trie::insert(root[tot], 19, x);
}
void del(int k) {tot -= k;}
void max_xor(int l, int r, int x) { //printf("max_xor %d %d %d\n", l, r, x);
    int ans = trie::max_xor(root[l-1], root[r], 19, x);
    printf("%d\n", ans);
}
void smaller(int l, int r, int x) {
    int ans = trie::small(root[l-1], root[r], 19, x);
    printf("%d\n", ans);
}
void kth(int l, int r, int k) { //printf("kth %d %d %d\n", l, r, k);
    int ans = trie::kth(root[l-1], root[r], 19, k);
    printf("%d\n", ans);
}
int main() {
    freopen("in", "r", stdin);
    Q = read();
    for(int i=1; i<=Q; i++) {
        op = read() - 1; //printf("\n-------------------- %d %d\n", i, op);
        if(op == 0) add(read());
        else if(op == 2) del(read());
        else {
            l = read(); r = read();
            if(op == 1) max_xor(l, r, read());
            else if(op == 3) smaller(l, r, read());
            else kth(l, r, read());
        }
    }
}

相關文章