[BZOJ 3166]Alo 可持久化01Trie
阿新 • • 發佈:2017-12-05
解決 高位到低位 max ins pre 操作 stream 我們 ons
這道題入門了 可持久化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; }
[BZOJ 3166]Alo 可持久化01Trie