【BZOJ】【P1251】【序列终结者】【题解】【Treap】

传送门:www.lydsy.com/JudgeOnline/problem.php?id=1251

练习一下可持久化Treap

Code:

//ID:zky
#include<cstdio>
#include<climits>
#include<iostream>
#include<algorithm>
using namespace std;
int rnd(){
	static int KEY=12345678;
	return KEY+=KEY<<2|1;
}
int tot;
struct node;
node *root,*Null;
struct node{
	int val,size,key,lazy,rev,maxx,ind;
	node *c[2];
	void split(int need,node *&p,node *&q);
	node(int _val,node *C){
		val=_val;size=1;
		key=rnd();lazy=rev=maxx=0;
		c[0]=c[1]=C;ind=tot++;
	}
	void add(int d){
		val+=d;
		lazy+=d;
		maxx+=d;
	}
	void Rev(){
		if(this==Null)return;
		rev^=1;
		swap(c[0],c[1]);
	}
	node *rz(){
		size=1;
		maxx=val;
		if(c[0]!=Null)
			size+=c[0]->size,maxx=max(maxx,c[0]->maxx);
		if(c[1]!=Null)
			size+=c[1]->size,maxx=max(maxx,c[1]->maxx);
		return this;
	}
	void pushdown(){
		if(this==Null)return;
		if(lazy){
			if(c[0]!=Null)
				c[0]->add(lazy);
			if(c[1]!=Null)
				c[1]->add(lazy);
			lazy=0;
		}
		if(rev){
			if(c[0]!=Null)
				c[0]->Rev();
			if(c[1]!=Null)
				c[1]->Rev();
			rev^=1;
		}
	}
};
node *merge(node *p,node *q){
	if(p==Null)return q->rz();
	if(q==Null)return p->rz();
	p->pushdown();q->pushdown();
	if(p->key<q->key){
		p->c[1]=merge(p->c[1],q);
		return p->rz();	
	}else{
		q->c[0]=merge(p,q->c[0]);
		return q->rz();
	}
}void deb(node *x){
	printf("#%d size:%d val:%d  lazy:%d  maxx:%d\n",x->ind,x->size,x->val,x->lazy,x->maxx);
	if(x->c[0]!=Null)
		printf("L:"),deb(x->c[0]);
	if(x->c[1]!=Null)
		printf("R:"),deb(x->c[1]);
}
void node::split(int need,node *&p,node *&q){
	if(this==Null){p=q=Null;return;}
	pushdown();
	if(c[0]->size>=need){
		c[0]->split(need,p,q);
		c[0]=Null;
		rz();
		q=merge(q,this);
	}else{
		c[1]->split(need-c[0]->size-1,p,q);
		c[1]=Null;
		rz();
		p=merge(this,p);
	}
} 

struct Treap{
	Treap(){
		Null=new node(0,0);
		Null->size=0;
		Null->c[0]=Null->c[1]=Null;
		Null->key=INT_MAX;Null->maxx=0;
		Null->val=Null->lazy=Null->rev=0;
		root=Null;
	}
	void rev(int l0,int r0){
		node *p,*q,*r,*s;
		root->split(l0-1,p,q);
		q->split(r0-l0+1,r,s);
		r->Rev();
		root=merge(p,merge(r,s));
	}
	void add(int l0,int r0,int d){
		node *p,*q,*r,*s;
		root->split(l0-1,p,q);
		q->split(r0-l0+1,r,s);
		r->add(d);r->pushdown();
		root=merge(p,merge(r,s));		
	}
	int Max(int l0,int r0){
		node *p,*q,*r,*s;
		root->split(l0-1,p,q);
		q->split(r0-l0+1,r,s);
		int ans=r->maxx;
		root=merge(p,merge(r,s));			
		return ans;
	}
}T;

int n,m;
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
		root=merge(root,new node(0,Null));
	while(m--){
		int opt,l,r,d;
		scanf("%d",&opt);
		if(opt==1){
			scanf("%d%d%d",&l,&r,&d);
			T.add(l,r,d);
		}else
		if(opt==2){
			scanf("%d%d",&l,&r);
			T.rev(l,r);
		}else{
			scanf("%d%d",&l,&r);
			printf("%d\n",T.Max(l,r));
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值