[BZOJ1251]序列终结者

[BZOJ1251]序列终结者

BZOJ
luogu
初学fhq_treap,调了真鸡儿久
感觉这东西比splay灵活,核心函数只有split和merge
其实码量倒是差不太多,splay也就一个rotate和一个splay
就把这题做入门题写了嗯嗯

#include<bits/stdc++.h>
using namespace std;
const int _=5e4+5;
int re(){
	int x=0,w=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
	return x*w;
}
int n,m,rt,tot;
int sz[_],ls[_],rs[_],mx[_],cov[_],rev[_],rd[_],val[_];
void rever(int x){rev[x]^=1;swap(ls[x],rs[x]);}
void cover(int x,int v){if(x)val[x]+=v,mx[x]+=v,cov[x]+=v;}
void pu(int x){
	sz[x]=sz[ls[x]]+sz[rs[x]]+1;
	mx[x]=max(val[x],max(mx[ls[x]],mx[rs[x]]));
}
void pd(int x){
	if(rev[x])rever(ls[x]),rever(rs[x]),rev[x]=0;
	if(cov[x])cover(ls[x],cov[x]),cover(rs[x],cov[x]),cov[x]=0;
}
void split(int x,int&l,int&r,int k){
	if(!x){l=r=0;return;}pd(x);
	if(k>=sz[ls[x]]+1)l=x,split(rs[x],rs[l],r,k-sz[ls[x]]-1),pu(l);
	else r=x,split(ls[x],l,ls[r],k),pu(r);
}
void merge(int&x,int l,int r){
	if(!l||!r){x=l|r;return;}pd(l);pd(r);
	if(rd[l]>rd[r]){x=l;merge(rs[x],rs[l],r);}
	else{x=r;merge(ls[x],l,ls[r]);}pu(x);
}
void add(int l,int r,int v){
	int x,y,z;
	split(rt,x,y,r);split(x,x,z,l-1);
	cover(z,v);merge(x,x,z);merge(rt,x,y);
}
void reverse(int l,int r){
	int x,y,z;
	split(rt,x,y,r);split(x,x,z,l-1);
	rever(z);merge(x,x,z);merge(rt,x,y);
}
int qmax(int l,int r){
	int x,y,z,res;
	split(rt,x,y,r);split(x,x,z,l-1);
	res=mx[z];merge(x,x,z),merge(rt,x,y);
	return res;
}
int main(){
	srand(time(NULL));
	n=re(),m=re();mx[0]=-1e9;
	for(int i=1;i<=n;i++){
		sz[i]=1;rd[i]=rand();merge(rt,rt,i);
	}
	int op,l,r,v;
	while(m--){
		op=re(),l=re(),r=re();
		if(op==1)v=re(),add(l,r,v);
		if(op==2)reverse(l,r);
		if(op==3)printf("%d\n",qmax(l,r));
	}
	return 0;
}
posted @ 2018-11-05 20:36  sdzwyq  阅读(128)  评论(0编辑  收藏  举报