1. 程式人生 > >【bzoj3281】最大異或和 可持久化Trie樹

【bzoj3281】最大異或和 可持久化Trie樹

log pac 序列 str char s pan pri scan bool

題目描述

給定一個非負整數序列 {a},初始長度為 N。
有M個操作,有以下兩種操作類型:
1、A x:添加操作,表示在序列末尾添加一個數 x,序列的長度 N+1。
2、Q l r x:詢問操作,你需要找到一個位置 p,滿足 l<=p<=r,使得:
a[p] xor a[p+1] xor ... xor a[N] xor x 最大,輸出最大是多少。

輸入

第一行包含兩個整數 N ,M,含義如問題描述所示。
第二行包含 N個非負整數,表示初始的序列 A 。
接下來 M行,每行描述一個操作,格式如題面所述。

輸出

假設詢問操作有 T個,則輸出應該有 T行,每行一個整數表示詢問的答案。

樣例輸入

5 5
2 6 4 3 6
A 1
Q 3 5 4
A 4
Q 5 7 0
Q 3 6 6

樣例輸出

4
5
6


題解

可持久化Trie樹

由於x xor x=0,所以$a_p\oplus a_{p+1}\oplus \cdots\oplus a_{n-1}\oplus a_n\oplus x=(a_1\oplus a_2\oplus\cdots\oplus a_{p-2}\oplus a_{p-1})\oplus(a_1\oplus a_2\oplus\cdots\oplus a_{n-1}\oplus a_{n})\oplus x$

維護一個前綴異或和,則這裏的sum[n] xor x是已知的,只要求出是這個值最大的sum[p-1]。

因為100000(2)>011111(2),所以可以把前綴和放到可持久化Trie樹中,然後貪心求解。

這裏需要註意的是l可能等於1,會使用到sum[0],而建立可持久化Trie樹時就要用到root[-1],所以把整個數組向右平移一位。

#include <cstdio>
#include <algorithm>
#define N 600010
using namespace std;
int sum[N] , next[N * 20][2] , si[N * 20] , tot , root[N];
char str[5];
int insert(int x , int v)
{
	int tmp , y , i;
	bool t;
	tmp = y = ++tot;
	for(i = 1 << 24 ; i ; i >>= 1)
	{
		next[y][0] = next[x][0] , next[y][1] = next[x][1] , si[y] = si[x] + 1;
		t = v & i , x = next[x][t] , next[y][t] = ++tot , y = next[y][t];
	}
	si[y] = si[x] + 1;
	return tmp;
}
int query(int x , int y , int v)
{
	int ret = 0 , i;
	bool t;
	for(i = 1 << 24 ; i ; i >>= 1)
	{
		t = v & i;
		if(si[next[y][t ^ 1]] - si[next[x][t ^ 1]]) ret += i , x = next[x][t ^ 1] , y = next[y][t ^ 1];
		else x = next[x][t] , y = next[y][t];
	}
	return ret;
}
int main()
{
	int n , m , i , x , y , z;
	scanf("%d%d" , &n , &m) , n ++ ;
	for(i = 2 ; i <= n ; i ++ ) scanf("%d" , &x) , sum[i] = sum[i - 1] ^ x;
	for(i = 1 ; i <= n ; i ++ ) root[i] = insert(root[i - 1] , sum[i]);
	while(m -- )
	{
		scanf("%s%d" , str , &x);
		if(str[0] == ‘A‘) n ++ , sum[n] = sum[n - 1] ^ x , root[n] = insert(root[n - 1] , sum[n]);
		else scanf("%d%d" , &y , &z) , printf("%d\n" , query(root[x - 1] , root[y] , sum[n] ^ z));
	}
	return 0;
}

【bzoj3281】最大異或和 可持久化Trie樹