zoukankan      html  css  js  c++  java
  • 「模板」 FHQ_Treap 区间翻转

    「模板」 FHQ_Treap 区间翻转

    <题目链接>


    没有旋转的 Treap 实现区间操作的功能,很好理解,也很好写,只是速度不算太快。

    对于要翻转的区间,把整棵 Treap(存有区间 ([1,n]) 的信息)Split 成 ([1,l-1])([l,r])([r+1,n]) 三部分,给中间部分的根节点打上标记,再一边下传标记一边 Merge 回来。

    注意 Split 时,要按元素个数,不能按权值,因为元素个数可以通过维护节点信息的 size 域而直接得到,但随着区间的翻转,权值会乱套。

    一定注意先推标记!!先推标记!!先推标记!!

    就因为标记推晚了,我调了一天。

    #include <algorithm>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <ctime>
    using std::swap;
    const int MAXN=100010;
    int n,m;
    class FHQ_Treap
    {
    	public:
    		FHQ_Treap(void)
    		{
    			rt=cnt=0;
    			memset(a,0,sizeof a);
    		}
    		void Insert(int x)
    		{
    			s[++cnt]=node(x,Random(),1);
    			Merge(rt,rt,cnt);
    		}
    		void Reverse(int x,int y)
    		{
    			int l=0,r=0,t=0;
    			Split(rt,x-1,l,t),Split(t,y-x+1,t,r);
    			s[t].lazy^=1,Merge(l,l,t),Merge(rt,l,r);
    		}
    		void Print(void)
    		{
    			DFS(rt),putchar('
    ');
    		}
    	private:
    		bool a[MAXN];
    		int rt,cnt;
    		struct node
    		{
    			int v,p,size,lazy,c[2];
    			node(int _v=0,int _p=0,int _size=0)
    			{
    				v=_v,p=_p,size=_size,lazy=0;
    				memset(c,0,sizeof c);
    			}
    		}s[MAXN];
    		int Random(void)
    		{
    			int x;
    			while(a[x=rand()%MAXN]);
    			a[x]=1;
    			return x;
    		}
    		void Update(int i)
    		{
    			s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1;
    		}
    		void PushDown(int i)
    		{
    			int &l=s[i].c[0],&r=s[i].c[1];
    			swap(l,r);
    			if(l)
    				s[l].lazy^=1;
    			if(r)
    				s[r].lazy^=1;
    			s[i].lazy=0;
    		}
    		void Split(int i,int x,int &l,int &r)
    		{
    			if(!i)
    			{
    				l=r=0;
    				return;
    			}
    			if(s[i].lazy)
    				PushDown(i);
    			int t=s[s[i].c[0]].size+1;
    			if(x<t)
    				Split(s[r=i].c[0],x,l,s[i].c[0]);
    			else
    				Split(s[l=i].c[1],x-t,s[i].c[1],r);
    			Update(i);
    		}
    		void Merge(int &i,int l,int r)
    		{
    			if(!l || !r)
    			{
    				i=l|r;
    				return;
    			}
    			if(s[l].p>s[r].p)
    			{
    				if(s[l].lazy)
    					PushDown(l);
    				Merge(s[i=l].c[1],s[l].c[1],r);
    			}
    			else
    			{
    				if(s[r].lazy)
    					PushDown(r);
    				Merge(s[i=r].c[0],l,s[r].c[0]);
    			}
    			Update(i);
    		}
    		void DFS(int i)
    		{
    			if(s[i].lazy)
    				PushDown(i);
    			if(s[i].c[0])
    				DFS(s[i].c[0]);
    			printf("%d ",s[i].v);
    			if(s[i].c[1])
    				DFS(s[i].c[1]);
    		}
    }T;
    int main(int argc,char *argv[])
    {
    	srand((unsigned)time(NULL));
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=n;++i)
    		T.Insert(i);
    	for(int i=1,l,r;i<=m;++i)
    	{
    		scanf("%d %d",&l,&r);
    		T.Reverse(l,r);
    	}
    	T.Print();
    	return 0;
    }
    

    谢谢阅读。

  • 相关阅读:
    我的知识库(4) java获取页面编码(Z)
    知识库(3)JAVA 正则表达式 (超详细)
    The Struts dispatcher cannot be found. This is usually caused by using Struts tags without the associated filter. Struts
    某人总结的《英语听力的技巧 》,挺搞的
    我的知识库(5)java单例模式详解
    构建可扩展程序
    SerialPort (RS232 Serial COM Port) in C# .NET
    Python学习笔记——String、Sequences
    UI题目我的答案
    jQuery学习系列学会操纵Form表单元素(1)
  • 原文地址:https://www.cnblogs.com/Capella/p/8506459.html
Copyright © 2011-2022 走看看