bzoj 1251 裸splay

裸的splay,只需要注意 max[-1]:=-maxlongint 就行了,否则在update的时候子节点的

max值会在max[-1]里选

/**************************************************************
     Problem: 1251
     User: BLADEVIL
     Language: Pascal
     Result: Accepted
     Time: 16008 ms
     Memory: 3448 kb
****************************************************************/
 
//By BLADEVIL
const
     sroot                   =- 1 ;
var
     n, m                    : longint ;
     i                       : longint ;
     a, father               : array [- 1..100010 ] of longint ;
     k, l, r, v              : longint ;
     root                    : longint ;
     max, size, tree         : array [- 1..100010 ] of longint ;
     val                     : array [- 1..100010 ] of longint ;
     flag                    : array [- 1..100010 ] of boolean ;
     son                     : array [- 1..100010 , 0..1 ] of longint ;
     
procedure swap( var a,b: longint );
var
     c                       : longint ;
begin
     c:=a; a:=b; b:=c;
end ;
     
function get_max(a,b: longint ): longint ;
begin
     if a>b then exit(a) else exit(b);
end ;
 
procedure renew_add(x,v: longint );
begin
     inc(tree[x],v); inc( val [x],v); inc(max[x],v);
end ;
 
procedure renew_reverse(x: longint );
begin
     swap(son[x, 1 ],son[x, 0 ]);
     flag[x]:= not flag[x];
end ;
     
procedure update(x: longint );
begin
     //if x=sroot then exit;
     max[x]:=get_max(tree[x],get_max(max[son[x, 1 ]],max[son[x, 0 ]]));
     size[x]:=size[son[x, 1 ]]+size[son[x, 0 ]]+ 1 ;
end ;
     
function build(l,r: longint ): longint ;
var
     mid                     : longint ;
begin
     mid:=(r+l) div 2 ;
     build:=mid;
     tree[mid]:=a[mid];
     if l+ 1 <=mid then
     begin
         son[mid, 0 ]:=build(l,mid- 1 );
         father[son[mid, 0 ]]:=mid;
     end ;
     if mid<=r- 1 then
     begin
         son[mid, 1 ]:=build(mid+ 1 ,r);
         father[son[mid, 1 ]]:=mid;
     end ;
     update(mid);
end ;
 
procedure push_down(x: longint );
var
     l, r                    : longint ;
begin
     l:=son[x, 0 ]; r:=son[x, 1 ];
     if flag[x] then
     begin
         if l<>- 1 then renew_reverse(l);
         if r<>- 1 then renew_reverse(r);
         flag[x]:= false ;
     end ;
     if val [x]<> 0 then
     begin
         if l<>- 1 then renew_add(l, val [x]);
         if r<>- 1 then renew_add(r, val [x]);
         val [x]:= 0 ;
     end ;
end ;
     
function find(x: longint ): longint ;
var
     t                       : longint ;
begin
     t:=root;
     while true do
     begin
         push_down(t);
         if size[son[t, 0 ]]+ 1 =x then exit(t);
         if size[son[t, 0 ]]+ 1 >x then t:=son[t, 0 ] else
         begin
             dec(x,size[son[t, 0 ]]+ 1 );
             t:=son[t, 1 ];
         end ;
     end ;
end ;
 
procedure rotate(x,y: longint );
var
     f                       : longint ;
begin
     push_down(x);
     f:=father[x];
     father[son[x,y xor 1 ]]:=f;
     son[f,y]:=son[x,y xor 1 ];
     if f=root then root:=x else
         if f=son[father[f], 0 ] then
             son[father[f], 0 ]:=x else
             son[father[f], 1 ]:=x;
     father[x]:=father[f];
     father[f]:=x;
     son[x,y xor 1 ]:=f;
     update(f);
     update(x);
end ;
 
procedure splay(x,y: longint );
var
     u, v                    : longint ;
begin
     while father[x]<>y do
     begin
         if father[father[x]]=y then
             rotate(x,ord(x=son[father[x], 1 ])) else
         begin
             if son[father[x], 0 ]=x then u:= 1 else u:=- 1 ;
             if son[father[father[x]], 0 ]=father[x] then v:= 1 else v:=- 1 ;
             if u*v= 1 then
             begin
                 rotate(father[x],ord(x=son[father[x], 1 ]));
                 rotate(x,ord(x=son[father[x], 1 ]));
             end else
             begin
                 rotate(x,ord(x=son[father[x], 1 ]));
                 rotate(x,ord(x=son[father[x], 1 ]));
             end ;
         end ;
     end ;
     update(x);
end ;
     
procedure add(l,r,v: longint );
var
     p                       : longint ;
begin
     p:=find(l);splay(p,sroot);
     p:=find(r+ 2 );splay(p,root);
     p:=son[son[root, 1 ], 0 ];
     renew_add(p,v);
end ;
 
procedure reverse(l,r: longint );
var
     p                       : longint ;
begin
     p:=find(l);splay(p,sroot);
     p:=find(r+ 2 );splay(p,root);
     p:=son[son[root, 1 ], 0 ];
     renew_reverse(p);
end ;
 
function ask_max(l,r: longint ): longint ;
var
     p                       : longint ;
begin
     p:=find(l); splay(p,sroot);
     p:=find(r+ 2 ); splay(p,root);
     p:=son[son[root, 1 ], 0 ];
     ask_max:=max[p];
end ;
     
begin
     fillchar(son,sizeof(son), 255 );
     read(n,m);
     max[- 1 ]:=-maxlongint;
     for i:= 1 to n do a[i]:= 0 ;
     inc(n);
     root:=build( 0 ,n);
     father[root]:=sroot;
     for i:= 1 to m do
     begin
         read(k);
         if k= 1 then
         begin
             read(l,r,v);
             add(l,r,v);
         end else
         begin
             read(l,r);
             if k= 2 then    
                 reverse(l,r) else
                 writeln (ask_max(l,r));
         end ;
     end ;
end .

 

转载于:https://www.cnblogs.com/BLADEVIL/p/3458357.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值