標籤:bzoj bzoj3217 替罪羊樹 trie樹 樹套樹
題目大意:維護一個序列,支援以下操作:
1.在某個位置插入一個數
2.刪除某個位置上的數
3.修改某個位置上的數
4.求某段區間中的次大值與區間中另一個數的異或值的最大值
強制線上
替罪羊樹套Trie樹。。。終於尼瑪A了。。。7.4KB的大代碼啊- -
插入和修改同帶插入區間k小值 刪除要打標記不能直接刪
刪除的時候注意 刪除導致的不平衡不要重建 否則複雜度無法保證
因此每個節點維護一個max_size代表曆史size最大值 判斷不平衡時用這個變數來判斷即可
注意訪問替罪羊樹的時候一定要判斷當前節點是否已被刪除- - 否則問題大大的- -
詢問時先找到次小值 然後找異或的最大值 注意不要二分 直接在替罪羊樹上找對應區間 具體寫法詳見代碼(如果能找到函數在哪裡的話- -)
還有啥注意事項。。。 變數重名,成員函數訪問錯誤,友元函數不引用本結構體指標,失效的預設值,忘記重載delete。。。我也是醉了
尼瑪萬惡的360把我家的渣渣C-Free給殺了- - 調試功能爆炸了,只能gdb- - 調過範例之後就沒心情再調了- -
#include <queue>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define M 200200#define L (1<<15)#define ALPHA 0.88using namespace std;class Trie *null;class Trie{private:static queue<Trie*> bin;public:Trie *son[2];int size;void* operator new (size_t,Trie *_,Trie *__,int ___){static Trie *mempool,*C=mempool;Trie *re;if( !bin.empty() )re=bin.front(),bin.pop();else{if(C==mempool)mempool=(C=new Trie[L])+L;re=C++;}re->son[0]=_;re->son[1]=__;re->size=___;return re;}void operator delete (void *p){bin.push((Trie*)p);}friend void Insert(Trie* &p,int num,int pos=1<<20){if(p==null)p=new (null,null,0) Trie;p->size++;if(!pos) return ;if(num&pos)Insert(p->son[1],num,pos>>1);elseInsert(p->son[0],num,pos>>1);}void Delete(int num,int pos=1<<20){size--;if(!pos) return ;if(num&pos)son[1]->Delete(num,pos>>1);elseson[0]->Delete(num,pos>>1);}int Get_Kth(int pos,int k){if(!pos) return 0;if(k<=son[1]->size)return pos|son[1]->Get_Kth(pos>>1,k);elsereturn son[0]->Get_Kth(pos>>1,k-son[1]->size);}int Get_Max(int pos,int x){int temp=pos&x?1:0;if(!pos) return 0;if(son[!temp]->size)return pos|son[!temp]->Get_Max(pos>>1,x);elsereturn son[temp]->Get_Max(pos>>1,x);}void Decomposition(){if(this==null)return ;son[0]->Decomposition();son[1]->Decomposition();delete this;}};class Kth_Getter{private:int first,second;public:Kth_Getter():first(-1),second(-1) {}bool Insert(int x){if(x>first){second=first;first=x;return true;}if(x>second)second=x;return false;}int Second(){return second;}};class Scapetree *nil,**to_rebuild;int to_delete;class Scapetree{private:static queue<Scapetree*> bin;public:static int stack[M],top;Scapetree *ls,*rs;int val,size,max_size;Trie *tree;void* operator new (size_t,Scapetree *_,Scapetree *__,int ___,int ____){static Scapetree *mempool,*C=mempool;Scapetree *re;if( !bin.empty() )re=bin.front(),bin.pop();else{if(C==mempool)mempool=(C=new Scapetree[L])+L;re=C++;}re->ls=_;re->rs=__;re->val=___;re->size=____;re->max_size=____;re->tree=null;return re;}void operator delete (void *p){bin.push((Scapetree*)p);}bool Check(){if((double)ls->max_size/max_size>ALPHA)return true;if((double)rs->max_size/max_size>ALPHA)return true;return false;}friend void Insert(Scapetree* &p,int pos,int val){int temp=~p->val?1:0;if(p==nil){p=new (nil,nil,val,1) Scapetree;Insert(p->tree,val);return ;}p->size++;Insert(p->tree,val);p->max_size=max(p->max_size,p->size);if(pos<=p->ls->size)Insert(p->ls,pos,val);elseInsert(p->rs,pos-p->ls->size-temp,val);if(p->Check())to_rebuild=&p;}void Delete(int pos){int temp=~val?1:0;if(pos<=ls->size)ls->Delete(pos);else{pos-=ls->size;if(pos==temp){to_delete=val;val=-1;}else rs->Delete(pos-temp);}size--;tree->Delete(to_delete);}void Modify(int pos,int val){int temp=~this->val?1:0;if(pos<=ls->size)ls->Modify(pos,val);else{pos-=ls->size;if(pos==temp){to_delete=Scapetree::val;Scapetree::val=val;}else rs->Modify(pos-temp,val);}tree->Delete(to_delete);Insert(tree,val);}void Decomposition(){if(this==nil)return ;ls->Decomposition();if(~val) stack[++top]=val;rs->Decomposition();tree->Decomposition();delete(this);}void Get_2th(int l,int r,Kth_Getter& getter){if( l==1 && r==size ){if( getter.Insert( tree->Get_Kth(1<<20,1) ) && size>=2 )getter.Insert( tree->Get_Kth(1<<20,2) );return ;}int temp=~val?1:0;if( temp && l<=ls->size+1 && r>=ls->size+1 )getter.Insert(val);if( l<=ls->size )ls->Get_2th(l,min(r,ls->size),getter);if( r>ls->size+temp )rs->Get_2th(max(l-(ls->size+temp),1),r-(ls->size+temp),getter);}int Get_Max(int l,int r,int val){if( l==1 && r==size )return tree->Get_Max(1<<20,val);int re=-1,temp=~this->val?1:0;if( temp && l<=ls->size+1 && r>=ls->size+1 )re=max(re,val^this->val);if( l<=ls->size )re=max(re,ls->Get_Max(l,min(r,ls->size),val) );if( r>ls->size+temp )re=max(re,rs->Get_Max(max(l-(ls->size+temp),1),r-(ls->size+temp),val) );return re;}void Output(){if(this==nil)return ;ls->Output();printf("---------------- %d\n",val);rs->Output();}}*root=nil;Scapetree* Build_Tree(int a[],int l,int r){if(l>r) return nil;int i,mid=l+r>>1;Scapetree *lson=Build_Tree(a,l,mid-1);Scapetree *rson=Build_Tree(a,mid+1,r);Scapetree *re=new (lson,rson,a[mid],r-l+1) Scapetree;for(i=l;i<=r;i++)Insert(re->tree,a[i]);return re;}queue<Trie*> Trie :: bin;queue<Scapetree*> Scapetree :: bin;int Scapetree :: stack[M];int Scapetree :: top;int n,m,last_ans;int a[M>>1];void Initialize(){null=new (0x0,0x0,0) Trie;null->son[0]=null->son[1]=null;nil=new (0x0,0x0,0,0) Scapetree;nil->ls=nil->rs=nil;}void Insert(int pos,int val){to_rebuild=0x0;Insert(root,pos,val);if(to_rebuild){Scapetree::top=0;(*to_rebuild)->Decomposition();(*to_rebuild)=Build_Tree(Scapetree::stack,1,Scapetree::top);}}int Query(int l,int r){Kth_Getter getter;root->Get_2th(l,r,getter);int val=getter.Second();return root->Get_Max(l,r,val);}int main(){#ifndef ONLINE_JUDGEfreopen("3217.in","r",stdin);freopen("3217.out","w",stdout);#endifint i,x,y;char p[100];Initialize();cin>>n>>m;for(i=1;i<=n;i++)scanf("%d",&a[i]);root=Build_Tree(a,1,n);for(i=1;i<=m;i++){scanf("%s",p);switch(p[0]){case 'I':scanf("%d%d",&x,&y);x=(x+last_ans)%(n++);y=(y+last_ans)%1048576;Insert(x,y);break;case 'D':scanf("%d",&x);x=(x+last_ans)%n+1;root->Delete(x);n--;break;case 'C':scanf("%d%d",&x,&y);x=(x+last_ans)%n+1;y=(y+last_ans)%1048576;root->Modify(x,y);break;case 'F':scanf("%d%d",&x,&y);x=(x+last_ans)%n+1;y=(y+last_ans)%n+1;if(x>y) swap(x,y);printf("%d\n", last_ans=Query(x,y) );break;}//root->Output();puts("");}return 0;}
BZOJ 3217 ALOEXT 替罪羊樹套Trie樹