说在前面
「可持久化」这个词含义还真多= =
其实可持久化trie实际上就是主席trie…?
题目
题面
给定一个非负整数序列 {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行,每行一个整数表示询问的答案。
解法
因为是在区间里查询,比较容易想到可持久化数据结构
但是询问操作查询的是后缀和,直接维护比较麻烦
然而异或是可以抵消的,也就是说a[p] xor … xor a[N]等价于( a[1] xor … xor a[N] ) xor ( a[1] xor .. a[p-1] )
所以可以把询问转化为前缀和查询,然后就可以瞎搞搞了=w=
代码实现的时候注意,如果L=1需要特判异或全部的情况。写了代码就会理解这句话的意思了
下面是自带大常数的代码
/**************************************************************
Problem: 3261
User: Izumihanako
Language: C++
Result: Accepted
Time:4860 ms
Memory:171916 kb
****************************************************************/
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
int N , M , rcnt , sum ;
struct Node{
int cnt ;
Node *ch[2] ;
}w[600005*24] , *tw = w , *root[600005] , null ;
void Insert( Node *las , Node *&nd , int num , int ws ){
nd = ++tw , nd->cnt = las->cnt + 1 ;
if( ws == -1 ) return ;
if( num&( 1<<ws ) ){
nd->ch[0] = las->ch[0] ;
Insert( las->ch[1] , nd->ch[1] , num , ws - 1 ) ;
} else{
nd->ch[1] = las->ch[1] ;
Insert( las->ch[0] , nd->ch[0] , num , ws - 1 ) ;
}
}
int Query( Node *lf , Node *rg , int x ){
for( int i = 23 ; i >= 0 ; i -- ){
int lsiz = rg->ch[0]->cnt - lf->ch[0]->cnt ,
rsiz = rg->ch[1]->cnt - lf->ch[1]->cnt ;
// printf( "hg(%d) lsiz(%d) rsiz(%d)\n" , i , lsiz , rsiz ) ;
if( x&(1<<i) ){
if( lsiz ) lf = lf->ch[0] , rg = rg->ch[0] ;
else lf = lf->ch[1] , rg = rg->ch[1] , x^=(1<<i) ;
} else {
if( rsiz ) lf = lf->ch[1] , rg = rg->ch[1] , x^=(1<<i) ;
else lf = lf->ch[0] , rg = rg->ch[0] ;
}
}
return x ;
}
void solve(){
char opt[5] ;
for( int i = 1 , L , R , x ; i <= M ; i ++ ){
scanf( "%s" , opt ) ;
switch( opt[0] ){
case 'A':{
scanf( "%d" , &x ) ;
sum ^= x , rcnt ++ ;
Insert( root[rcnt-1] , root[rcnt] , sum , 23 ) ;
break ;
}
default :{
scanf( "%d%d%d" , &L , &R , &x ) ;
int ans = Query( root[ max(L-2,0) ] , root[R-1] , x^sum ) ;
if( L == 1 ) ans = max( ans , x ^ sum ) ;
printf( "%d\n" , ans ) ;
}
}
}
}
int main(){
null.ch[0] = null.ch[1] = &null ;
root[0] = ++tw ; *root[0] = null ;
scanf( "%d%d" , &N , &M ) ;
for( int i = 1 , tmp ; i <= N ; i ++ ){
scanf( "%d" , &tmp ) ;
sum ^= tmp , rcnt ++ ;
Insert( root[rcnt-1] , root[rcnt] , sum , 23 ) ;
}
solve() ;
}