【bzoj1251】序列终结者 splay

AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1251

【题解】

splay的练习题目。

切掉模板之后应该没有问题了。

注意mx[0]=-INF

/*************
  bzoj 1251
  by chty
  2016.12.26
*************/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
#define FILE "read"
#define MAXN 50010
#define inf 0x7fffffff
#define up(i,j,n) for(int i=j;i<=n;i++)
#define dn(i,j,n) for(int i=j;i>=n;i--)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
namespace INIT{
	char buf[1<<15],*fs,*ft;
	inline char getc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
	inline int read(){
		int x=0,f=1;  char ch=getc();
		while(!isdigit(ch)) {if(ch=='-')  f=-1;  ch=getc();}
		while(isdigit(ch)) {x=x*10+ch-'0';  ch=getc();}
		return x*f;
	}
}using namespace INIT;
int n,m,root;
namespace Splay_Tree{
	int son[MAXN][2],f[MAXN],v[MAXN],size[MAXN],mx[MAXN],delta[MAXN],vis[MAXN];
	bool get(int x){return son[f[x]][1]==x;}
	void updata(int x){
		size[x]=size[son[x][0]]+size[son[x][1]]+1; 
		mx[x]=max(mx[son[x][0]],mx[son[x][1]]);
		mx[x]=max(mx[x],v[x]);
	}
	void rotate(int x){
		int y=f[x],z=f[y],which=get(x);
		son[y][which]=son[x][which^1];  f[son[y][which]]=y;
		son[x][which^1]=y;  f[y]=x;  f[x]=z;
		if(z) son[z][son[z][1]==y]=x;
		updata(y);  updata(x);
	}
	void splay(int x,int k){
		for(int y;(y=f[x]);rotate(x)){
			if(x==k)  break;
			else if(y==k) {rotate(x);  break;}
			else if(f[y]==k) {rotate(get(x)==get(y)?y:x);  rotate(x); break;}
			else rotate(get(x)==get(y)?y:x);
		}
		if(k==root)  root=x;
	}
	void pushdown(int x){
		if(delta[x]){
			if(son[x][0]) delta[son[x][0]]+=delta[x],v[son[x][0]]+=delta[x],mx[son[x][0]]+=delta[x];
			if(son[x][1]) delta[son[x][1]]+=delta[x],v[son[x][1]]+=delta[x],mx[son[x][1]]+=delta[x];
			delta[x]=0;
		}
		if(vis[x]){
			swap(son[x][0],son[x][1]);
			vis[son[x][0]]^=1;  vis[son[x][1]]^=1;  vis[x]=0;
		}
	}
	int find(int x){
		int now=root;
		while(1){
			if(vis[now]||delta[now]) pushdown(now);
			int temp=size[son[now][0]];
			if(x<=temp)  now=son[now][0];
			else{
				if(x==temp+1)  return now;
				x-=temp+1;
				now=son[now][1];
			}
		}
	}
	void build(int l,int r,int p){
		if(l>r)  return;
		if(l==r){son[p][l>=p]=l;f[l]=p;size[l]=1;return;}
		int mid=(l+r)>>1;
		build(l,mid-1,mid);  build(mid+1,r,mid);
		son[p][mid>=p]=mid;  f[mid]=p;  updata(mid);
	}
	void change(int l,int r,int value){
		int x=find(l),y=find(r+2);
		splay(x,root);  splay(y,son[root][1]);
		int z=son[y][0];
		delta[z]+=value;  mx[z]+=value;  v[z]+=value;
	}
	void rever(int l,int r){
		int x=find(l),y=find(r+2);
		splay(x,root);  splay(y,son[root][1]);
		vis[son[y][0]]^=1;
	}
	void query(int l,int r){
		int x=find(l),y=find(r+2);
		splay(x,root);  splay(y,son[root][1]);
		printf("%d\n",mx[son[y][0]]);
	}
}using namespace Splay_Tree;
int main(){
	freopen(FILE".in","r",stdin);
	freopen(FILE".out","w",stdout);
	n=read();  m=read();  mx[0]=-inf;
	build(1,n+2,0);  root=(n+3)>>1;
	up(i,1,m){
		int flag=read(),l=read(),r=read(),value;
		switch(flag){
			case 1:value=read();change(l,r,value);break;
			case 2:rever(l,r);break;
			case 3:query(l,r);break;
		}
	}
	return 0;
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值