bzoj 1500 修改区间 splay

内个我也不知道哪儿不对,TLE了,说说思路吧

其实思路也没什么说的,就是裸的splay,对于最后一个操作

我们记下每个区间的最长前缀,最长后缀,那么最长子序列就是

前缀,后缀,左子树的后缀+右子树的前缀+自己的值,里取max就行了

更新的时候前缀由左子树的前缀,左子树sum+右子树前缀转移

靠!!!!!!到底哪儿错了!!!!!TLE 你妹啊!!!!!

 

/**************************************************************
    Problem: 1500
    User: BLADEVIL
    Language: Pascal
    Result: Time_Limit_Exceed
****************************************************************/
 
//By BLADEVIL
const
    sroot                   =-1;
     
var
    n, m                    :int64;
    a                       :array[-1..500010] of int64;
    root                    :int64;
    father, key, size       :array[-1..500010] of int64;
    son                     :array[-1..500010,0..1] of int64;
    flag                    :array[-1..500010] of boolean;
    val, sum                :array[-1..500010] of int64;
    pred, succ              :array[-1..500010] of int64;
     
procedure swap(var a,b:int64);
var
    c                       :int64;
begin
    c:=a; a:=b; b:=c;
end;
     
function get_max(a,b:int64):int64;
begin
    if a>b then exit(a) else exit(b);
end;
     
procedure update(x:int64);
begin
    if x=sroot then exit;
    size[x]:=size[son[x,0]]+size[son[x,1]]+1;
    sum[x]:=sum[son[x,0]]+sum[son[x,1]]+key[x];
    pred[x]:=get_max(pred[son[x,0]],sum[son[x,0]]+pred[son[x,1]]+key[x]);
    succ[x]:=get_max(succ[son[x,1]],sum[son[x,1]]+succ[son[x,0]]+key[x]);
end;
 
procedure c_renew(x,y:int64);
begin
    key[x]:=y; sum[x]:=size[x]*y;
    pred[x]:=get_max(y,sum[x]);
    succ[x]:=get_max(y,sum[x]);
    val[x]:=y;
end;
 
procedure r_renew(x:int64);
begin
    swap(son[x,0],son[x,1]);
    flag[x]:=not flag[x];
end;
 
procedure push_down(x:int64);
var
    l, r                    :int64;
begin
    l:=son[x,0]; r:=son[x,1];
    if flag[x] then
    begin
        if l<>-1 then r_renew(l);
        if r<>-1 then r_renew(r);
        flag[x]:=false;
    end;
    if val[x]<>0 then
    begin
        if l<>-1 then c_renew(l,val[x]);
        if r<>-1 then c_renew(r,val[x]);
        val[x]:=0;
    end;
end;
     
function build(l,r:int64):int64;
var
    mid                     :int64;
begin
    mid:=(l+r) div 2;
    key[mid]:=a[mid];
    build:=mid;
    if mid-1>=l then
    begin
        son[mid,0]:=build(l,mid-1);
        father[son[mid,0]]:=mid;
    end;
    if mid+1<=r then
    begin
        son[mid,1]:=build(mid+1,r);
        father[son[mid,1]]:=mid;
    end;
    update(mid);
end;
 
procedure rotate(x,y:int64);
var
    f                       :int64;
begin
    push_down(x);
    f:=father[x];
    son[f,y]:=son[x,y xor 1];
    father[son[x,y xor 1]]:=f;
    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:int64);
var
    u, v                    :int64;
begin
    while father[x]<>y do
    if father[father[x]]=y then
        rotate(x,ord(x=son[father[x],1]))
    else
    begin
        if x=son[father[x],0] then u:=1 else u:=-1;
        if father[x]=son[father[father[x]],0] then v:=1 else v:=-1;
        if v*u=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;
    update(x);
end;
 
function find(k:int64):int64;
var
    t                       :int64;
begin
    t:=root;
    while true do
    begin
        push_down(t);
        if size[son[t,0]]+1=k then exit(t);
        if size[son[t,0]]+1>k then t:=son[t,0] else
        begin
            dec(k,size[son[t,0]]+1);
            t:=son[t,1];
        end;
    end;
end;
 
procedure insert;
var
    i                       :longint;   
    l, s                    :int64;
    p, q                    :int64;
begin
    read(l,s);
    for i:=n+1 to n+s do read(a[i]);
    readln;
    q:=build(n+1,n+s);
    n:=n+s;
    p:=find(l+1); splay(p,sroot);
    p:=find(l+2); splay(p,root);
    p:=son[root,1];
    father[q]:=p;
    son[p,0]:=q;
    update(p);
    update(root);
end;
 
procedure delete;
var
    p                       :int64;
    l, s                    :int64;
begin
    readln(l,s);
    p:=find(l); splay(p,sroot);
    p:=find(l+s+1); splay(p,root);
    p:=son[son[root,1],0];
    father[p]:=-1;
    son[son[root,1],0]:=-1;
    update(son[root,1]);
    update(root);
end;
 
procedure change;
var
    l, s, c                 :int64;
    p                       :int64;
begin
    readln(l,s,c);
    p:=find(l); splay(p,sroot);
    p:=find(l+s+1); splay(p,root);
    p:=son[son[root,1],0];
    c_renew(p,c);
    update(son[root,1]);
    update(root);
end;
 
procedure reverse;
var
    p                       :int64;
    l, s                    :int64;
begin
    readln(l,s);
    p:=find(l); splay(p,sroot);
    p:=find(l+s+1); splay(p,root);
    p:=son[son[root,1],0];
    r_renew(p);
    //update(son[root,1]);
    //update(root);
end;
     
procedure get_sum;
var
    l, s                    :int64;
    p                       :int64;
begin
    readln(l,s);
    p:=find(l); splay(p,sroot);
    p:=find(l+s+1); splay(p,root);
    p:=son[son[root,1],0];
    writeln(sum[p]);
end;
     
procedure max_sum;
var
    l, r                    :int64;
begin
    readln;
    l:=son[root,0]; r:=son[root,1];
    writeln(get_max(succ[l]+pred[r]+key[root],get_max(pred[l],succ[r])));
end;
     
procedure main;
var
    i                       :longint;
    ss                      :ansistring;
    ch                      :char;
begin
    fillchar(son,sizeof(son),255);
    read(n,m);
    for i:=1 to n do read(a[i]);
    inc(n);
    root:=build(0,n);
    father[root]:=sroot;
    readln;
    for i:=1 to m do
    begin
        read(ch);
        ss:='';
        while ch<>' ' do
        begin
            ss:=ss+ch;
            read(ch);
            if ss='MAX-SUM' then break;
        end;
        if ss='INSERT' then insert else
        if ss='DELETE' then delete else
        if ss='MAKE-SAME' then change else
        if ss='REVERSE' then reverse else
        if ss='GET-SUM' then get_sum else
        if ss='MAX-SUM' then max_sum;
    end;
end;
 
begin
    main;
end.

 

posted on 2013-12-11 21:38  BLADEVIL  阅读(358)  评论(0编辑  收藏  举报