标签: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.88 using 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); else Insert(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); else son[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); else return 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); else return 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); else Insert(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_JUDGE freopen("3217.in","r",stdin); freopen("3217.out","w",stdout); #endif int 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 bzoj3217 替罪羊树 trie树 树套树
原文地址:http://blog.csdn.net/popoqqq/article/details/42237085