2018.10.05 codevs1743 反转卡片(非旋treap)

传送门
非旋treap维护区间反转简单题。
很板的一道题。
fhq_treap真心好些,安利一波。
只需要写 m e r g e , s p l i t merge,split merge,split两个操作,并且及时的下穿标记与合并信息就行了。
代码:

#include<bits/stdc++.h>
#define N 300005
#define lc son[p][0]
#define rc son[p][1]
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
typedef pair<int,int> pii;
struct Treap{
	int son[N][2],siz[N],tag[N],val[N],rt,tot,rd[N];
	inline void pushup(int p){siz[p]=siz[lc]+siz[rc]+1;}
	inline void pushdown(int p){
		if(tag[p]){
			swap(lc,rc);
			if(lc)tag[lc]^=1;
			if(rc)tag[rc]^=1;
			tag[p]^=1;
		}
	}
	inline int newnode(int v){return val[++tot]=v,siz[tot]=1,rd[tot]=rand(),tot;}
	inline int merge(int a,int b){
		if(!a||!b)return a+b;
		if(rd[a]<rd[b])return pushdown(a),son[a][1]=merge(son[a][1],b),pushup(a),a;
		return pushdown(b),son[b][0]=merge(a,son[b][0]),pushup(b),b;
	}
	inline pii split(int p,int k){
		if(!p)return pii(0,0);
		pii ans,tmp;
		pushdown(p);
		if(siz[lc]>=k){
			tmp=split(lc,k),ans.first=tmp.first,ans.second=p,lc=tmp.second,pushup(p);
			return ans;
		}
		tmp=split(rc,k-siz[lc]-1),ans.second=tmp.second,ans.first=p,rc=tmp.first,pushup(p);
		return ans;
	}
}T;
int n;
int main(){
	T.rt=T.tot=0,srand(time(NULL));
	n=read();
	for(int i=1;i<=n;++i){
		int v=read();
		T.rt=T.merge(T.rt,T.newnode(v));
	}
	int tim=0;
	while(1){
		pii x=T.split(T.rt,1);
		T.pushdown(T.rt),T.rt=T.merge(x.first,x.second);
		if(T.val[x.first]==1)return printf("%d",tim),0;
		++tim,x=T.split(T.rt,T.val[x.first]),T.tag[x.first]^=1,T.rt=T.merge(x.first,x.second);
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值