Splay(sequence)

原題:NOI 2005 維護數列

方法:單旋SPLAY

program sequences;{$inline on}{start at 6:42}
const maxn=500005;
var
    l,r,w,s,sum,max,lm,rm,c,ss:array[0..maxn]of longint;
    rev:array[0..maxn]of boolean; top,k:longint;
procedure update(var x:longint;const t:longint);
begin
    if t>x then x:=t;
end;
procedure update(const x:longint);
var ll,rr:longint;
begin
    ll:=l[x];rr:=r[x];s[x]:=s[ll]+s[rr]+1;
    sum[x]:=sum[ll]+sum[rr]+w[x];
    lm[x]:=lm[ll];rm[x]:=rm[rr];
    update(lm[x],lm[rr]+sum[ll]+w[x]);
    update(rm[x],rm[ll]+sum[rr]+w[x]);
    max[x]:=rm[ll]+lm[rr]+w[x];
    update(max[x],max[ll]);update(max[x],max[rr]);
end;
procedure left(var i:longint);var j:longint;
begin
    j:=r[i];r[i]:=l[j];l[j]:=i;
    update(i);update(j);i:=j;
end;
procedure right(var i:longint);var j:longint;
begin
    j:=l[i];l[i]:=r[j];r[j]:=i;
    update(i);update(j);i:=j;
end;
procedure put(const i,cc:longint;f:boolean);var t:longint;
begin
    if i=0 then exit;
    if f then begin
	t:=l[i];l[i]:=r[i];r[i]:=t;
	t:=lm[i];lm[i]:=rm[i];rm[i]:=t;
	rev[i]:=not rev[i];
    end;
    if cc<$400 then begin
	c[i]:=cc;w[i]:=cc;sum[i]:=cc*s[i];
	max[i]:=0;update(max[i],sum[i]);
	lm[i]:=max[i];rm[i]:=max[i];
	if max[i]=0 then max[i]:=cc;
    end;
end;
procedure splay(var i:longint;const k:longint);
begin
    put(l[i],c[i],rev[i]);put(r[i],c[i],rev[i]);
    rev[i]:=false; c[i]:=$400;
    if s[l[i]]+1=k then exit;
    if s[l[i]]+1>k then begin
	splay(l[i],k); right(i);
    end else begin
	splay(r[i],k-s[l[i]]-1); left(i);
    end;
end;
procedure build(var x:longint;const ll,rr:longint);
begin
    if ll>rr then exit;x:=(ll+rr)>>1;
    build(l[x],ll,x-1);build(r[x],x+1,rr);
    update(x);
end;
procedure release(const x:longint);
begin
    if x=0 then exit;inc(top);ss[top]:=x;
    release(l[x]);release(r[x]);
end;
var n,m,i,pos,tot,root:longint; ch,ct:char;
begin
    assign(input,'input.txt');	reset(input);
    assign(output,'output.txt');rewrite(output);
    readln(n,m);fillchar(c,sizeof(c),127);
    w[1]:=-maxint;w[n+2]:=-maxint;max[0]:=-maxint;
    for i:=2 to n+1 do read(w[i]);build(root,1,n+2);
    for i:=maxn downto n+3 do begin inc(top);ss[top]:=i;end;
    for m:=1 to m do begin
	repeat read(ch); until ch in ['A'..'Z','-'];
	read(ch);read(ch);
	repeat read(ct); until ct in [' ',#13,#10,#26];
	if ch<>'X' then read(pos,tot);
	case ch of
	'S':begin
	    splay(root,pos+2);
	    for tot:=1 to tot do begin
		k:=ss[top+1-tot];
		read(w[k]);c[k]:=$400;rev[k]:=false;
		l[k]:=0;r[k]:=0;
	    end;
	    l[ss[top]]:=l[root];l[root]:=ss[top];k:=tot;
	    for tot:=1 to tot-1 do r[ss[top+1-tot]]:=ss[top-tot];
	    for tot:=tot+1 downto 1 do update(ss[top+1-tot]);
	    update(root);dec(top,k);
	end;
	'L':begin
	    splay(root,pos);splay(root,pos+tot+1);
	    release(r[l[root]]);r[l[root]]:=0;
	    update(l[root]);update(root);
	end;
	'K':begin
	    splay(root,pos);splay(root,pos+tot+1);read(k);
	    put(r[l[root]],k,false);
	    update(l[root]);update(root);
	end;
	'V':begin
	    splay(root,pos);splay(root,pos+tot+1);
	    put(r[l[root]],$400,true);
	    update(l[root]);update(root);
	end;
	'T':begin
	    splay(root,pos);splay(root,pos+tot+1);
	    writeln(sum[r[l[root]]]);
	end;
	'X':writeln(max[root]);
	end;
    end;
    close(input);close(output);
end.


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章