[BZOJ1500]维修序列

5 篇文章 0 订阅
5 篇文章 0 订阅

传说中的splay tree模版题之完全体?

代码写的弱。。。跑的慢。。。据说区间操作其实不需要分裂?

有时间再优化一下吧。。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=500010;
const int inf=500000000;
int root;
int a[maxn],siz[maxn],lm[maxn],rm[maxn],s[2][maxn],sum[maxn],v[maxn],mx[maxn],n,m,stk[maxn],t; 
bool sflag[maxn],flag[maxn];
char S[20];
int cmp(int ro,int k){
	if (siz[s[0][ro]]+1==k) return -1;
	return k<siz[s[0][ro]]+1?0:1;
}
void maintain(int now){
	lm[now]=max(lm[s[0][now]],sum[s[0][now]]+v[now]+lm[s[1][now]]);
	rm[now]=max(rm[s[1][now]],sum[s[1][now]]+v[now]+rm[s[0][now]]);
	mx[now]=max(rm[s[0][now]]+v[now]+lm[s[1][now]],max(mx[s[0][now]],mx[s[1][now]]));
	sum[now]=sum[s[0][now]]+sum[s[1][now]]+v[now];
	siz[now]=siz[s[0][now]]+siz[s[1][now]]+1;
}
void change(int ro,int samev){
	sflag[ro]=1;
	v[ro]=samev;
	sum[ro]=samev*siz[ro];
	lm[ro]=rm[ro]=max(sum[ro],0);
	mx[ro]=max(sum[ro],v[ro]);
}
void pushdown(int ro){
	if (sflag[ro]){
		if (s[0][ro]) change(s[0][ro],v[ro]);
		if (s[1][ro]) change(s[1][ro],v[ro]);
		sflag[ro]=0;
	}
	if (flag[ro]){
		swap(s[0][ro],s[1][ro]);
		if (s[0][ro]){
			flag[s[0][ro]]^=1;
			swap(lm[s[0][ro]],rm[s[0][ro]]);
		}
		if (s[1][ro]){
			flag[s[1][ro]]^=1;
			swap(lm[s[1][ro]],rm[s[1][ro]]);	
		}
		flag[ro]=0;
	}
}
void rotate(int &ro,int d){
	int tmp=s[d^1][ro];
	pushdown(ro);pushdown(tmp); 
	s[d^1][ro]=s[d][tmp];
	s[d][tmp]=ro;
	maintain(ro);maintain(tmp);
	ro=tmp;
}
void splay_kth(int &ro,int k){
	pushdown(ro);
	int d1=cmp(ro,k);
	if (d1==1) k-=siz[s[0][ro]]+1;
	if (d1!=-1){
		int p=s[d1][ro];
		pushdown(p);
		int d2=cmp(p,k);
		if (d2!=-1){
			int k2=(d2==0)?k:k-siz[s[0][p]]-1;
			splay_kth(s[d2][p],k2);
			if (d1==d2) rotate(ro,d1^1);
			else rotate(s[d1][ro],d1);
		}
		rotate(ro,d1^1);
	}
}
void split (int ro,int len,int &le,int &ri){
	splay_kth(ro,len);
	le=ro;ri=s[1][ro];s[1][ro]=0;
	maintain(le);maintain(ri);
}
int merge(int le,int ri){
	splay_kth(le,siz[le]);
	s[1][le]=ri;
	maintain(le);
	return le;
}
int build(int l,int r){
	if (l==r){
		int now=stk[t--];
		mx[now]=sum[now]=a[l];
		lm[now]=rm[now]=max(0,a[l]);
		s[0][now]=s[1][now]=0;
		sflag[now]=flag[now]=0;
		v[now]=a[l];
		siz[now]=1;
		return now; 
	}
	int now=stk[t--];
	int mid=(l+r)>>1;
	if (l<mid) s[0][now]=build(l,mid-1);
	else s[0][now]=0;
	s[1][now]=build(mid+1,r);
	sflag[now]=flag[now]=0;
	v[now]=a[mid];
	maintain(now);
	return now;
}
void insert(int pos,int n){
	int ro1=build(1,n);
	int ro2=0;
	split(root,pos+1,root,ro2);
	root=merge(merge(root,ro1),ro2);
}
void recycle(int ro){
	stk[++t]=ro;
	if (s[0][ro])recycle(s[0][ro]);
	if (s[1][ro])recycle(s[1][ro]);
	return ;
}
void del(int pos,int n){
	int ro1,ro2;
	ro1=ro2=0;
	split(root,pos,root,ro1);
	split(ro1,n,ro1,ro2);
	recycle(ro1);
	root=merge(root,ro2);
}
void samev(int pos,int n,int samev){
	int ro1,ro2;
	ro1=ro2=0;
	split(root,pos,root,ro1);
	split(ro1,n,ro1,ro2);
	change(ro1,samev);
	root=merge(root,merge(ro1,ro2));
} 
void reverse(int pos,int n){
	int ro1,ro2;
	ro1=ro2=0;
	split(root,pos,root,ro1);
	split(ro1,n,ro1,ro2);
	flag[ro1]^=1;
	swap(lm[ro1],rm[ro1]);
	root=merge(root,merge(ro1,ro2));
}
void get_sum(int pos,int n){
	int ro1,ro2;
	ro1=ro2=0;
	split(root,pos,root,ro1);
	split(ro1,n,ro1,ro2);
	printf("%d\n",sum[ro1]);
	root=merge(root,merge(ro1,ro2));
}
int main(){
	#ifndef ONLINE_JUDGE
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
	#endif
	for (int i=500000;i>=1;i--) stk[++t]=i;
	scanf("%d%d",&n,&m);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	a[0]=-inf;n++;a[n]=-inf;
	lm[0]=rm[0]=0;mx[0]=-inf;
	sum[0]=v[0]=siz[0]=0;
	root=build(0,n);
	for (int i=1;i<=m;i++){
		scanf("%s",&S);
		int pos,c;
		switch(S[2]){
			case 'S': //INSERT_posi_tot_ci
			scanf("%d%d",&pos,&n);
			if (n<=0) break;
			for (int i=1;i<=n;i++) scanf("%d",&a[i]);
			insert(pos,n);
			break;
			case 'L': //DELETE_posi_tot
			scanf("%d%d",&pos,&n);
			if (n<=0) break;
			del(pos,n);
			break;
			case 'K': //MAKE-SAME_posi_tot_c
			scanf("%d%d%d",&pos,&n,&c);
			if (n<=0) break;
			samev(pos,n,c);
			break;
			case 'V': //REVERSE_posi_tot
			scanf("%d%d",&pos,&n);
			if (n<=0) break;
			reverse(pos,n);
			break;
			case 'T': //GET-SUM_posi_tot
			scanf("%d%d",&pos,&n);
			if (n<=0){
				printf("0\n");
				break;
			}
			get_sum(pos,n);
			break;
			case 'X': //MAX-SUM
			printf("%d\n",mx[root]);
			break;
		}
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值