这道题入门了 可持久化01Trie
可持久化Trie多数用来解决区间异或k值之类的操作,主要是由高位到低位按位贪心就可以了
其实和主席树是一样的,Trie本身也有前缀相减性,至于空间,动态开点就可以了。
当然我们需要记录每个节点的size
对于这道题,我们可以用线段树处理出每一个数作为次大值的区间,然后去区间的Trie里面查询异或最大值就可以了
#include<iostream>
#include<cstdio>
#include<cstring>
#define pos(i,a,b) for(int i=(a);i<=(b);i++)
#define pos2(i,a,b) for(int i=(a);i>=(b);i--)
#define N 50100
#include<vector>
#include<algorithm>
using namespace std;
int n;
int a[N],pos[N],lisan[N];
vector<int> b;
int findx(int x){
return lower_bound(b.begin(),b.end(),x)-b.begin()+1;
}
int sum[N*4];
bool cmp(const int &x,const int &y){
return x>y;
}
struct haha{
int left,right;
}cun[N];
int query_r(int pos,int l,int r,int rt){
if(pos<=0) return 0;
if(sum[rt]==0) return 0;
if(l==r) return l;
int mid=(l+r)>>1;
if(pos<=mid) return query_r(pos,l,mid,rt<<1);
else{
int ans=query_r(pos,mid+1,r,rt<<1|1);
if(ans!=0) return ans;
return query_r(pos,l,mid,rt<<1);
}
}
int query_l(int pos,int l,int r,int rt){
if(pos>=n+1) return n+1;
if(sum[rt]==0) return n+1;
if(l==r) return l;
int mid=(l+r)>>1;
if(pos>mid) return query_l(pos,mid+1,r,rt<<1|1);
else{
int ans=query_l(pos,l,mid,rt<<1);
if(ans!=n+1) return ans;
return query_l(pos,mid+1,r,rt<<1|1);
}
}
void update(int pos,int l,int r,int rt){
if(l==r){sum[rt]++;return;}
int mid=(l+r)>>1;
if(pos<=mid) update(pos,l,mid,rt<<1);
else update(pos,mid+1,r,rt<<1|1);
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
struct Trie{
Trie *ch[2];int size;
Trie(){ch[0]=ch[1]=NULL;size=0;}
}*root[N];
int bit[33];
void insert(Trie *&rt,Trie *rt_pre,int num){
Trie *now=rt,*old=rt_pre;
pos2(i,31,0){
int d=num&bit[i];if(d) d=1;else d=0;
if(old==NULL){
if(now->ch[d]==NULL) now->ch[d]=new Trie();
now->ch[d]->size++;
now=now->ch[d];
}
else{
now->ch[d^1]=old->ch[d^1];
if(now->ch[d]==NULL) now->ch[d]=new Trie();
int add(0);if(old->ch[d]!=NULL) add=old->ch[d]->size;
now->ch[d]->size=add+1;
now=now->ch[d];
old=old->ch[d];
}
}
}
int ans;
int query(int l,int r,int num){
Trie *nowl=root[l-1],*nowr=root[r];
int res(0);
pos2(i,31,0){
int d=num&bit[i];if(d) d=1;else d=0;
if(nowl==NULL){
if(nowr->ch[d]==NULL){
nowr=nowr->ch[d^1];
if(d^1) res|=bit[i];
continue;
}
if(nowr->ch[d^1]==NULL){
nowr=nowr->ch[d];
if(d) res|=bit[i];
continue;
}
nowr=nowr->ch[d^1];
if(d^1) res|=bit[i];
}
else{
if(nowr->ch[d]==NULL){
nowr=nowr->ch[d^1];
if(d^1) res|=bit[i];
nowl=nowl->ch[d^1];
continue;
}
if(nowr->ch[d^1]==NULL){
nowr=nowr->ch[d];
if(d) res|=bit[i];
nowl=nowl->ch[d];
continue;
}
int add(0);
if(nowl->ch[d^1]!=NULL) add=nowl->ch[d^1]->size;
int size=nowr->ch[d^1]->size - add;
if(size>=1){
nowr=nowr->ch[d^1];
nowl=nowl->ch[d^1];
if(d^1) res|=bit[i];
}
else{
nowr=nowr->ch[d];
nowl=nowl->ch[d];
if(d) res|=bit[i];
}
}
}
return num^res;
}
int main(){
scanf("%d",&n);
root[0]=new Trie();
bit[0]=1;
pos(i,1,31) bit[i]=bit[i-1]<<1;
pos(i,1,n){
scanf("%d",&a[i]);b.push_back(a[i]);
root[i]=new Trie();
insert(root[i],root[i-1],a[i]);
}
sort(b.begin(),b.end());
pos(i,1,n){
pos[findx(a[i])]=i;
}
sort(a+1,a+n+1,cmp);
update(pos[findx(a[1])],1,n,1);
pos(i,2,n){
int lisan=findx(a[i]);
int posi=pos[lisan];
int j1=query_r(posi-1,1,n,1);
if(j1!=0) cun[lisan].left=query_r(j1-1,1,n,1)+1;
int j2=query_l(posi+1,1,n,1);
if(j2!=n+1) cun[lisan].right=query_l(j2+1,1,n,1)-1;
update(posi,1,n,1);
}
pos(i,2,n){
int lisan=findx(a[i]),posi=pos[lisan];
if(cun[lisan].left!=0){
ans=max(ans,query(cun[lisan].left,posi-1,a[i]));
}
if(cun[lisan].right!=0){
ans=max(ans,query(posi+1,cun[lisan].right,a[i]));
}
}
printf("%d",ans);
return 0;
}
原文:http://www.cnblogs.com/Hallmeow/p/7985770.html