zoukankan      html  css  js  c++  java
  • 「模板」 树套树

    「模板」 树套树

    <题目链接>


    线段树套 SBT。

    有生以来写过的最长代码。

    #include <algorithm>
    #include <climits>
    #include <cstdio>
    using std::max;
    using std::min;
    const int MAXN=50010;
    int n,m;
    class SegmentTree
    {
    	private:
    		int a[MAXN];
    		class SBT
    		{
    			private:
    				struct Node
    				{
    					int v,size;
    					Node *c[2];
    					Node(int v):v(v),size(1)
    					{
    						c[0]=c[1]=nullptr;
    					}
    					~Node(void)
    					{
    						if(c[0]!=nullptr)
    							delete c[0];
    						if(c[1]!=nullptr)
    							delete c[1];
    					}
    					int Size(bool p)
    					{
    						return c[p]!=nullptr ? c[p]->size : 0;
    					}
    					int SubSize(bool p,bool q)
    					{
    						return c[p]!=nullptr ? c[p]->Size(q) : 0;
    					}
    					void Update(void)
    					{
    						size=Size(0)+Size(1)+1;
    					}
    				}*rt;
    				void Rotate(Node* &i,bool p)
    				{
    					Node *t=i->c[!p];
    					i->c[!p]=t->c[p];
    					t->c[p]=i;
    					i->Update();
    					(i=t)->Update();
    				}
    				void Maintain(Node* &i,bool p)
    				{
    					int t=i->Size(!p);
    					if(t<i->SubSize(p,p))
    						Rotate(i,!p);
    					else if(t<i->SubSize(p,!p))
    					{
    						Rotate(i->c[p],p);
    						Rotate(i,!p);
    					}
    					else
    						return;
    					Maintain(i->c[0],0);
    					Maintain(i->c[1],1);
    					Maintain(i,0);
    					Maintain(i,1);
    				}
    				void Insert(Node* &i,int x)
    				{
    					if(i==nullptr)
    					{
    						i=new Node(x);
    						return;
    					}
    					bool p=x>i->v;
    					++i->size;
    					Insert(i->c[p],x);
    					Maintain(i,p);
    				}
    				void Delete(Node* &i,int x)
    				{
    					if(i==nullptr)
    						return;
    					if(x==i->v)
    						if(i->c[1]==nullptr)
    						{
    							Node *t=i;
    							i=i->c[0];
    							t->c[0]=t->c[1]=nullptr;
    							delete t;
    							return;
    						}
    						else
    						{
    							Node *t=i->c[1];
    							while(t->c[0]!=nullptr)
    								t=t->c[0];
    							i->v=t->v;
    							Delete(i->c[1],t->v);
    						}
    					else
    						Delete(i->c[x>i->v],x);
    					i->Update();
    				}
    			public:
    				SBT(int* a,int l,int r):rt(nullptr)
    				{
    					for(int i=l;i<=r;++i)
    						Insert(a[i]);
    				}
    				~SBT(void)
    				{
    					delete rt;
    				}
    				void Insert(int x)
    				{
    					Insert(rt,x);
    				}
    				void Delete(int x)
    				{
    					Delete(rt,x);
    				}
    				int Rank(int x)
    				{
    					int ans=1;
    					Node *i=rt;
    					while(i!=nullptr)
    						if(x>i->v)
    						{
    							ans+=i->Size(0)+1;
    							i=i->c[1];
    						}
    						else
    							i=i->c[0];
    					return ans-1;
    				}
    				int Prev(int x)
    				{
    					int ans=-INT_MAX;
    					Node *i=rt;
    					while(i!=nullptr)
    						if(x>i->v)
    						{
    							ans=max(ans,i->v);
    							i=i->c[1];
    						}
    						else
    							i=i->c[0];
    					return ans;
    				}
    				int Next(int x)
    				{
    					int ans=INT_MAX;
    					Node *i=rt;
    					while(i!=nullptr)
    						if(x<i->v)
    						{
    							ans=min(ans,i->v);
    							i=i->c[0];
    						}
    						else
    							i=i->c[1];
    					return ans;
    				}
    		};
    		struct Node
    		{
    			SBT *T;
    			int l,r;
    			Node *c[2];
    			Node(SBT* T,int l,int r):T(T),l(l),r(r)
    			{
    				c[0]=c[1]=nullptr;
    			}
    			~Node(void)
    			{
    				delete T;
    				if(c[0]!=nullptr)
    					delete c[0];
    				if(c[1]!=nullptr)
    					delete c[1];
    			}
    		}*rt;
    		void Build(Node* &i,int l,int r)
    		{
    			i=new Node(new SBT(a,l,r),l,r);
    			if(l^r)
    			{
    				int mid=l+r>>1;
    				Build(i->c[0],l,mid);
    				Build(i->c[1],mid+1,r);
    			}
    		}
    		int Rank(Node* i,int l,int r,int k)
    		{
    			if(l==i->l && r==i->r)
    				return i->T->Rank(k);
    			int mid=i->l+i->r>>1;
    			if(r<=mid)
    				return Rank(i->c[0],l,r,k);
    			else if(l>mid)
    				return Rank(i->c[1],l,r,k);
    			else
    				return Rank(i->c[0],l,mid,k)+Rank(i->c[1],mid+1,r,k);
    		}
    		void Modify(Node* i,int pos,int k)
    		{
    			i->T->Delete(a[pos]);
    			i->T->Insert(k);
    			if(pos==i->l && pos==i->r)
    				return;
    			int mid=i->l+i->r>>1;
    			if(pos>mid)
    				Modify(i->c[1],pos,k);
    			else
    				Modify(i->c[0],pos,k);
    		}
    		int Prev(Node* i,int l,int r,int k)
    		{
    			if(l==i->l && r==i->r)
    				return i->T->Prev(k);
    			int mid=i->l+i->r>>1;
    			if(r<=mid)
    				return Prev(i->c[0],l,r,k);
    			else if(l>mid)
    				return Prev(i->c[1],l,r,k);
    			else
    				return max(Prev(i->c[0],l,mid,k),Prev(i->c[1],mid+1,r,k));
    		}
    		int Next(Node* i,int l,int r,int k)
    		{
    			if(l==i->l && r==i->r)
    				return i->T->Next(k);
    			int mid=i->l+i->r>>1;
    			if(r<=mid)
    				return Next(i->c[0],l,r,k);
    			else if(l>mid)
    				return Next(i->c[1],l,r,k);
    			else
    				return min(Next(i->c[0],l,mid,k),Next(i->c[1],mid+1,r,k));
    		}
    	public:
    		SegmentTree(int n):rt(nullptr)
    		{
    			for(int i=1;i<=n;++i)
    				scanf("%d",&a[i]);
    			Build(rt,1,n);
    		}
    		~SegmentTree(void)
    		{
    			delete rt;
    		}
    		void Rank(void)
    		{
    			int l,r,k;
    			scanf("%d %d %d",&l,&r,&k);
    			printf("%d
    ",Rank(rt,l,r,k)+1);
    		}
    		void Find(void)
    		{
    			int l,r,k,left=0,right=int(1e8),mid;
    			scanf("%d %d %d",&l,&r,&k);
    			while(left<right)
    			{
    				int mid=left+right>>1;
    				if(k>Rank(rt,l,r,mid))
    					left=mid+1;
    				else
    					right=mid;
    			}
    			printf("%d
    ",left-1);
    		}
    		void Modify(void)
    		{
    			int pos,k;
    			scanf("%d %d",&pos,&k);
    			Modify(rt,pos,k);
    			a[pos]=k;
    		}
    		void Prev(void)
    		{
    			int l,r,k;
    			scanf("%d %d %d",&l,&r,&k);
    			printf("%d
    ",Prev(rt,l,r,k));
    		}
    		void Next(void)
    		{
    			int l,r,k;
    			scanf("%d %d %d",&l,&r,&k);
    			printf("%d
    ",Next(rt,l,r,k));
    		}
    };
    int main(int argc,char** argv)
    {
    	scanf("%d %d",&n,&m);
    	static SegmentTree *T=new SegmentTree(n);
    	for(int i=1,opt;i<=m;++i)
    	{
    		scanf("%d",&opt);
    		switch(opt)
    		{
    			case 1:
    				T->Rank();
    				break;
    			case 2:
    				T->Find();
    				break;
    			case 3:
    				T->Modify();
    				break;
    			case 4:
    				T->Prev();
    				break;
    			case 5:
    				T->Next();
    				break;
    		}
    	}
    	delete T;
    	return 0;
    }
    

    谢谢阅读。

  • 相关阅读:
    Android开发学习笔记-关于Android的消息推送以及前后台切换
    C#文件操作工具类
    c#取得应用程序根目录
    Visual Studio 2012中使用GitHub
    C#邮件发送
    jquery判断某个属性是否存在 hasAttr
    js 如何让两个等长的数组产生键值对关系
    js判断一个元素是否在数组中
    日期控件
    react 生命周期函数的一些心得体会
  • 原文地址:https://www.cnblogs.com/Capella/p/9092486.html
Copyright © 2011-2022 走看看