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

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());
		}
	}
}

posted @ 2017-05-05 19:28  Candy?  阅读(270)  评论(0编辑  收藏  举报