序列终结者 c语言,BZOJ-1251: 序列终结者(Splay)

代码(用splay树维护区间,注意每次不是直接splay(l-1,roof),splay(r+1,R[roof])而是splay(select(l-1,roof),roof),splay(select(r+1,R[roof]),R[roof])):

#include

#include

#include

#include

using namespace std;

#define MAXN 50010

#define L(t) T[t].left

#define R(t) T[t].right

#define M(t) T[t].Max

#define D(t) T[t].delta

#define F(t) T[t].flag

#define S(t) T[t].size

#define K(t) T[t].key

#define C(r,t) (S(L(t))>r)

#define inf 0x7fffffff

struct node {

int left,right,Max,delta,size,key;

bool flag;

node(){left=right=delta=flag=size=Max=key=0;}

} T[MAXN];

int roof=0,v=0,n,m;

void Insert(int &t) {

if (!t){S(t=++v)=1;return ;}

S(t)++; Insert(R(t));

}

void pushdown(int t) {

if (t){

if (F(t))

{swap(L(t),R(t));F(L(t))^=true,F(R(t))^=true;F(t)^=true;}

if (D(t))

{M(t)+=D(t),K(t)+=D(t);D(L(t))+=D(t),D(R(t))+=D(t);D(t)=0;}

}

}

void update(int t)

{pushdown(L(t)),pushdown(R(t));S(t)=S(L(t))+S(R(t))+1;M(t)=max(max(M(L(t)),M(R(t))),K(t));}

void zag(int &t) {

int k;pushdown(t);pushdown(k=R(t));

R(t)=L(k);update(t);L(k)=t;update(k);

t=k;

}

void zig(int &t) {

int k;pushdown(t);pushdown(k=L(t));

L(t)=R(k);update(t);R(k)=t;update(k);

t=k;

}

bool splay(int r,int &t,bool flag) {

pushdown(t);

if (S(L(t))==r) return false;

bool w=splay(C(r,t)?r:r-S(L(t))-1,C(r,t)?L(t):R(t),true);

if (!w){if (!flag){if (C(r,t)) zig(t); else zag(t);}

} else {

if (C(r,t))

{pushdown(L(t));if (C(r,L(t))) zig(t) ; else zag(L(t));zig(t);} else

{pushdown(R(t));if (!C(r-S(L(t))-1,R(t))) zag(t) ; else zig(R(t));zag(t);}

}

return w^true;

}

int main() {

M(0)=-inf;

scanf("%d%d",&n,&m);

for (int i=0;i<=n+1;i++) Insert(roof),splay(i,roof,false);

while (m--) {

int x,l,r;

scanf("%d%d%d",&x,&l,&r);

splay(l-1,roof,false);splay(r-S(L(roof)),R(roof),false);

pushdown(roof);pushdown(R(roof));pushdown(L(R(roof)));

if (x==1) {scanf("%d",&x);D(L(R(roof)))+=x;} else

{

if (x==2) {F(L(R(roof)))^=true;} else printf("%d\n",M(L(R(roof))));

}

}

return 0;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值