【BZOJ】1500: [NOI2005]维修数列-splay

这篇博客详细解析了BZOJ 1500题目的解决方案,重点介绍了如何利用Splay树模板解决这道题目。内容包括题解和代码实现,特别提醒了在处理过程中需要注意的四个关键点:pushup时的边界条件、赋值标记的初始化、每次操作后的pushup以及数据量大时的内存池管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

传送门:bzoj1500


题解

splay模板题,推荐一篇题解

一些注意事项:

1.t[0].mx=v[1]=v[n+2]=-inf,在 p u s h u p pushup pushup时会和子节点的 m x mx mx m a x max max,最后答案可能为负,所以要设为 − i n f -inf inf

2.st=inf,赋值标记要初始化为一个不在值域范围 [ − 1000 , 1000 ] [-1000,1000] [1000,1000]内的数

3.pushup(y);pushup(x);每次操作完记得 p u s h u p pushup pushup

4.数据点数过多,需要存内存池动态维护标号。


代码

#include<bits/stdc++.h>
using namespace std;
const int N=5e5+10;

int n,m,v[N];
char cmmd[50],cc;

char cp;
inline void rd(int &x)
{
    cp=getchar();x=0;int f=0;
    for(;!isdigit(cp);cp=getchar()) if(cp=='-') f=1;
    for(;isdigit(cp);cp=getchar()) x=(x<<3)+(x<<1)+(cp^48);
    if(f) x=-x;
}

namespace BST{
   #define lc(x) t[(x)].ch[0]
   #define rc(x) t[(x)].ch[1]
   #define F(x) t[(x)].fa
   
   int rt,stk[N],top;
   
   struct node{
   	  int ch[2],fa,rv,st,sz;
   	  int lx,rx,mx,sum,val;
   	  inline void itia(){ch[0]=ch[1]=fa=rv=0;}
   	  inline void mk(int x){lx=rx=mx=sum=val=x;st=N;sz=1;} 
   	  inline void cg(int x){val=st=x;sum=sz*x;mx=max(x,sum);lx=rx=max(0,sum);}
   	  inline void rev(){rv^=1;swap(ch[0],ch[1]);swap(lx,rx);}
   }t[N];
   
   struct pol{
   	  int cnt,q[N],top;
   	  inline void psh(int x){q[++top]=x;t[x].itia();}
   	  inline int nw(){if(top) return q[top--];return ++cnt;}
   }pl;
   
   inline void pushdown(int x)
   {
   	    if(t[x].st!=N){
   	    	if(lc(x)) t[lc(x)].cg(t[x].st);
			if(rc(x)) t[rc(x)].cg(t[x].st);
			t[x].st=N;
   	    }
   	    if(t[x].rv){
   	    	if(lc(x)) t[lc(x)].rev();
   	    	if(rc(x)) t[rc(x)].rev();
   	    	t[x].rv=0;
   	    }
   }
   
   inline void pushup(int x)
   {
   	  int l=lc(x),r=rc(x);
   	  t[x].sz=t[l].sz+t[r].sz+1;
   	  t[x].sum=t[l].sum+t[r].sum+t[x].val;
   	  t[x].mx=max(max(t[l].mx,t[r].mx),t[l].rx+t[x].val+t[r].lx);
   	  t[x].lx=max(t[l].lx,t[l].sum+t[x].val+t[r].lx);
   	  t[x].rx=max(t[r].rx,t[r].sum+t[x].val+t[l].rx);
   }
   
   inline void rot(int x)
   {
   	   int y=F(x),z=F(y),dr=(rc(y)==x);
   	   t[y].ch[dr]=t[x].ch[dr^1];if(t[y].ch[dr]) F(t[y].ch[dr])=y;
   	   F(x)=z;if(z) t[z].ch[(rc(z)==y)]=x;
   	   F(y)=x;t[x].ch[dr^1]=y;pushup(y);
   }
   
   inline void splay(int x,int gl)
   {
   	   int y,z;top=0;
   	   for(y=x;y;y=F(y)) stk[++top]=y;
	   for(;top;--top) pushdown(stk[top]);
	   if(F(x)==gl) return;if(!gl) rt=x;
   	   for(;F(x)!=gl;rot(x)){
   	   	  y=F(x);z=F(y);
   	   	  if(z!=gl) ((rc(y)==x)^(rc(z)==y))?rot(x):rot(y);
   	   }
   	   pushup(x);if(F(x)) pushup(F(x));
   }
   
   inline int kth(int x)
   {
   	   for(int u=rt,re;;){
   	   	  pushdown(u);re=t[lc(u)].sz+1;
   	   	  if(x==re) return u;
   	   	  if(x<re) u=lc(u);else x-=re,u=rc(u);
   	   }
   }
   
   int build(int l,int r)
   {
   	  if(l>r) return 0;
   	  int x=pl.nw(),mid=(l+r)>>1;t[x].mk(v[mid]);
   	  lc(x)=build(l,mid-1);rc(x)=build(mid+1,r);
   	  F(lc(x))=F(rc(x))=x;pushup(x);return x;
   }
   
   inline void ins()
   {
   	   int i,x,y,cur;
   	   rd(x);rd(y);
   	   for(i=1;i<=y;++i) rd(v[i]);
   	   cur=build(1,y);y=kth(x+2);x=kth(x+1);
   	   splay(x,0);splay(y,rt);
	   lc(y)=cur;F(cur)=y;
	   pushup(y);pushup(x);
   }
   
   void del(int x){if(lc(x)) del(lc(x));if(rc(x)) del(rc(x));pl.psh(x);}
}

int main(){
	using namespace BST;
	int i,x,y,z;
	rd(n);rd(m);
	t[0].mx=v[1]=v[n+2]=-1e9;
	for(i=2;i<=n+1;++i) rd(v[i]);
	rt=build(1,n+2);
	for(;m;--m){
		scanf("%s",cmmd);cc=cmmd[0];
		if(cc=='M' && cmmd[2]=='X') printf("%d\n",t[rt].mx);
		else if(cc=='I') ins();
		else{
		    rd(x);rd(y);
			y=kth(x+y+1);x=kth(x);
			splay(x,0);
			splay(y,rt);
			if(cc=='D') {F(lc(y))=0;del(lc(y));lc(y)=0;}
			else if(cc=='M'){rd(z);t[lc(y)].cg(z);}
			else if(cc=='R') t[lc(y)].rev();
			else printf("%d\n",t[lc(y)].sum);
			pushup(y);pushup(x);
		}
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值