BZOJ 1500 维护(维修?)数列

题目描述:http://www.lydsy.com/JudgeOnline/problem.php?id=1500


题解:

splay模板。

但是好难打啊QWQ

哭着求llgyc大神给了份模板开始抄。还要提高自己的数据结构水平啊。


参考代码:

#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define rep(i,a,b) for (int i=a; i<=b; i++)
#define per(i,a,b) for (int i=a; i>=b; i--)
using namespace std;
typedef long long LL;
	
inline int read() {
	int x=0,f=1; char ch=getchar();
	while (!(ch>='0'&&ch<='9')) {if (ch=='-')f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9') {x=x*10+(ch-'0'); ch=getchar();}
	return x*f;
}
 
const int N = 500005;
const int INF = 100000000;
 
int n,m,cnt=0,root;
int a[N];
int lc[N],rc[N],val[N],fa[N],size[N],lmax[N],rmax[N],mx[N],sum[N],rev[N],tag[N];
int head=1,tail=0,q[N];
 
inline void init() {rep(i,1,N-1) q[i]=i;}
inline int newn() {int ret=q[head]; head=(head+1)%N;lc[ret]=rc[ret]=rev[ret]=lmax[ret]=rmax[ret]=mx[ret]=0;return ret;}
inline void release(int x) {q[tail]=x; tail=(tail+1)%N;}
inline void del(int x) {if (!x) return; release(x); del(lc[x]); del(rc[x]);}
 
inline void pushdown(int x) {
	if (rev[x]) {
		rev[x]^=1; rev[lc[x]]^=1; rev[rc[x]]^=1;
		swap(lc[x],rc[x]); swap(lmax[x],rmax[x]);
	}
	if (tag[x]!=-INF) {
		tag[lc[x]]=tag[x]; tag[rc[x]]=tag[x];
		val[x]=tag[x]; sum[x]=tag[x]*size[x];
		lmax[x]=rmax[x]=mx[x]=max(tag[x],tag[x]*size[x]);
		tag[x]=-INF;
	}
}
 
inline void pushup(int x) {
	size[x]=size[lc[x]]+size[rc[x]]+1;
	sum[x]=sum[lc[x]]+sum[rc[x]]+val[x];
	lmax[x]=max(lmax[lc[x]],sum[lc[x]]+val[x]+max(lmax[rc[x]],0));
	rmax[x]=max(rmax[rc[x]],sum[rc[x]]+val[x]+max(rmax[lc[x]],0));
	mx[x]=max(val[x]+max(max(rmax[lc[x]],lmax[rc[x]]),max(0,lmax[rc[x]]+rmax[lc[x]])),max(mx[lc[x]],mx[rc[x]]));
}
 
inline int build(int x,int l,int r) {
	if (l>r) return 0;
	if (l==r) {
		cnt=newn(); val[cnt]=a[l]; fa[cnt]=x; tag[cnt]=-INF;
		pushup(cnt); return cnt;
	}
	int mid=(l+r)>>1;
	int ret=newn(); val[ret]=a[mid]; fa[ret]=x; tag[ret]=-INF;
	lc[ret]=build(ret,l,mid-1); rc[ret]=build(ret,mid+1,r);
	pushup(ret); return ret;
}
 
inline void rotate(int x) {
	int y=fa[x],z=fa[y],b;
	if (x==lc[y]) b=rc[x]; else b=lc[x];
	fa[x]=z; fa[y]=x; if (b) fa[b]=y;
	if (z) {if (lc[z]==y) lc[z]=x; else rc[z]=x;}
	if (x==lc[y]) rc[x]=y,lc[y]=b; else lc[x]=y,rc[y]=b;
	pushup(y); pushup(x);
}
 
int stk[N];
inline void splay(int x,int goal=0) {
	int top=0; stk[++top]=x; for (int i=x;i!=root;i=fa[i]) stk[++top]=fa[i];
	while (top) pushdown(stk[top--]);
	while (fa[x]!=goal) {
		int y=fa[x],z=fa[y];
		if (z!=goal) {
			if ((lc[z]==y)^(lc[y]==x)) rotate(x);
			else rotate(y);
		}
		rotate(x);
	}
	if (!goal) root=x;
}
 
inline int find(int k) {
	int x=root;
	while (1) {
		if (lc[x]) pushdown(lc[x]); 
		if (rc[x]) pushdown(rc[x]);
		if (size[lc[x]]+1==k) return x;
		if (size[lc[x]]>=k) x=lc[x];else k-=(size[lc[x]]+1),x=rc[x];
	}
}

inline void Insert(int pos,int num){
	rep(i,1,num) a[i]=read();
	int k1=find(pos+1),k2=find(pos+2);
	splay(k1);splay(k2,k1);
	lc[k2]=build(k2,1,num);
	pushup(k2);pushup(k1);
}

inline void Delete(int pos,int num){
	int k1=find(pos),k2=find(pos+num+1);
	splay(k1);splay(k2,k1);del(lc[k2]);
	lc[k2]=0;pushup(k2);pushup(k1);
}

inline void Modify(int pos,int num,int c){
	int k1=find(pos),k2=find(pos+num+1);
	splay(k1);splay(k2,k1);
	tag[lc[k2]]=c;pushdown(lc[k2]);
	pushup(k2);pushup(k1);
}

inline void Reverse(int pos,int num){
	int k1=find(pos),k2=find(pos+num+1);
	splay(k1);splay(k2,k1);
	rev[lc[k2]]^=1;pushdown(lc[k2]);
	pushup(k2);pushup(k1);
}

inline void getSum(int pos,int num){
	if(!num){printf("0\n");return;}
	int k1=find(pos),k2=find(pos+num+1);
	splay(k1);splay(k2,k1);
	pushdown(lc[k2]);pushup(k2);pushup(k1);
	printf("%d\n",sum[lc[k2]]); 
}

int main() {
	init(); n=read(),m=read(); rep(i,1,n) a[i]=read(); a[0]=a[n+1]=-INF; 
	lmax[0]=rmax[0]=mx[0]=tag[0]=-INF; root=build(0,0,n+1);
	char opt[20];
	while (m--) {
		scanf("%s",opt); int pos,num,c;
		switch(opt[0]){  
			case 'I':scanf("%d%d",&pos,&num);Insert(pos,num);break;  
			case 'D':scanf("%d%d",&pos,&num);Delete(pos,num);break;  
			case 'R':scanf("%d%d",&pos,&num);Reverse(pos,num);break;  
			case 'G':scanf("%d%d",&pos,&num);getSum(pos,num);break;  
			case 'M':if(o pt[2]=='K') {scanf("%d%d%d",&pos,&num,&c);Modify(pos,num,c);}else printf("%d\n",mx[root]);  
		}  
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值