2019.01.14【LOJ105】【洛谷P3391】文艺平衡树(FHQ treap)

版权声明:转载请声明出处,谢谢配合。 https://blog.csdn.net/zxyoi_dreamer/article/details/86482092

LOJ传送门

洛谷传送门


解析:

很久没有写过平衡树了,恢复一下手感。

FHQ_treap本身好写且常数不大。这道题只需要维护区间翻转,每次提取一个区间只需要按照 s i z siz 关键字 s p l i t split 出需要操作的序列部分来,然后该打标记的打标记,该下传的时候下传就行了。


代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc put_char
#define cs const

namespace IO{
	namespace IOONLY{
		cs int Rlen=1<<18|1;
		char buf[Rlen],*p1,*p2;
		char obuf[Rlen],*p3=obuf;
		char ch[23];
	}
	inline char get_char(){
		using namespace IOONLY;
		return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
	}
	inline void put_char(char c){
		using namespace IOONLY;
		*p3++=c;
		if(p3==obuf+Rlen)fwrite(obuf,1,Rlen,stdout),p3=obuf;
	}
	inline void FLUSH(){
		using namespace IOONLY;
		fwrite(obuf,1,p3-obuf,stdout),p3=obuf;
	}
	
	inline int getint(){
		re int num;
		re char c;
		re bool f=0;
		while(!isdigit(c=gc()))if(c=='-')f=1;num=c^48;
		while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
		return f?-num:num;
	}
	inline void outint(ll a){
		using namespace IOONLY;
		if(a==0)pc('0');
		if(a<0)pc('-'),a=-a;
		while(a)ch[++ch[0]]=a-a/10*10,a/=10;
		while(ch[0])pc(ch[ch[0]--]^48);
	}
}
using namespace IO;

cs int N=100005;
namespace FHQ_treap{
	namespace Vars{
		int son[N][2];
		int val[N];
		int siz[N];
		char pri[N];
		bool rev[N];
		int tot;
	}
	inline int newnode(int _val){
		using namespace Vars;
		int now=++tot;
		son[now][0]=son[now][1]=0;
		val[now]=_val;
		siz[now]=1;
		rev[now]=0;
		pri[now]=rand();
		return now;
	}
	
	inline void pushup(int now){
		using namespace Vars;
		siz[now]=siz[son[now][0]]+siz[son[now][1]]+1;
	}
	
	inline void pushdown(int now){
		using namespace Vars;
		if(rev[now]){
			swap(son[now][0],son[now][1]);
			if(son[now][0])rev[son[now][0]]^=1;
			if(son[now][1])rev[son[now][1]]^=1;
			rev[now]=0;
		}
	}
	
	pair<int,int> split_siz(int now,cs int &key){
		using namespace Vars;
		if(!now)return make_pair(0,0);
		pushdown(now);
		pair<int,int> res;
		if(key<siz[son[now][0]]+1){
			res=split_siz(son[now][0],key);
			son[now][0]=res.second;
			res.second=now;
		}
		else {
			res=split_siz(son[now][1],key-siz[son[now][0]]-1);
			son[now][1]=res.first;
			res.first=now;
		}
		pushup(now);
		return res;
	}
	
	int merge(int lc,int rc){
		using namespace Vars;
		if(!lc||!rc)return lc+rc;
		pushdown(lc),pushdown(rc);
		if(pri[lc]<pri[rc]){
			son[lc][1]=merge(son[lc][1],rc);
			pushup(lc);
			return lc;
		}
		else {
			son[rc][0]=merge(lc,son[rc][0]);
			pushup(rc);
			return rc;
		}
	}
	
	inline int rev_range(int now,int l,int r){
		using namespace Vars;
		pair<int,int> res1=split_siz(now,r);
		pair<int,int> res2=split_siz(res1.first,l-1);
		rev[res2.second]^=1;
		return merge(merge(res2.first,res2.second),res1.second);
	}
	
	void inorder_dfs(int now){
		using namespace Vars;
		if(!now)return ;
		pushdown(now);
		inorder_dfs(son[now][0]);
		outint(val[now]),pc(' ');
		inorder_dfs(son[now][1]);
	}
	
	int build(int l,int r){
		if(l==r)return newnode(l);
		int mid=(l+r)>>1;
		return merge(build(l,mid),build(mid+1,r));
	}
}
using namespace FHQ_treap;
int root,n,m;

signed main(){
	srand(time(0));
	n=getint(),m=getint();
	root=build(1,n);
	while(m--){
		int l=getint(),r=getint();
		root=rev_range(root,l,r);
	}
	inorder_dfs(root);
	FLUSH();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zxyoi_dreamer/article/details/86482092