终于写过了,在这里庆祝一下。
在开始前先推荐一篇论文运用伸展树解决数列维护问题,jzp大神写的关于splay树区间操作的方法。
这题很考验代码的细节能力。(大神可以忽略下面弱菜的一些弱弱心得了)
首先是初始化,初始化中的两个节点的初值应要因题而异,在本题中因为要求一个节点的max值,故两个节点的初值不能随便赋值,而应把初值赋为-INF,否则会导致结果错误。(在几千的数据里差错真心纠结....)
之后GET-SUM操作和DELETE操作还有INSER T操作和MAKE-SAME操作都是标准操作,找splay模板写即可,其中要注意一点的是删除时要注意回收内存。
REVERSE操作中,标记往下传时要对左右子树的标记xor 1,而不能简单地赋值为1(因为有可能在pushdown前子树已经要翻转)
MAX-SUM操作比较麻烦,可以用三个标记分别为lmax,rmax,mmax表示从左到右最大的sum值,从右起最大的sum值,还有整棵子树中sum值,然后求节点的lmax值可以分为三种情况,分别为左子树的lmax,整棵左子树的sum+节点的值,还有左子树的值+节点的值+右子树的lmax。求rmax同样也可以类似地分为三种情况。
求mmax的值首先可以想到取左右子树中mmax值较大的,之后再以节点为中心,向左右拓展找较大的序列,看这个序列的sum值是否比mmax大,若大则更新即可。
这道题几乎把splay的一些常用操作都涉及到了,故要学splay的话还是应该找个时间静心做一下。
下面先上代码(求大神不鄙视...)
const
MAXN=500000;
INF=10000000;
type
date=record
ch:array[0..1]of longint;
sz,v,f,sum,same,rev,mmax,rmax,lmax:longint;
end;
var
n,m,top,root,tst,p,tot,x,i:longint;s:string;
a,st:array[1..MAXN+10]of longint;
t:array[0..MAXN+10]of date;
procedure swap(var a,b:longint);
var c:longint;
begin
c:=a;a:=b;b:=c;
end;
function max(a,b:longint):longint;
begin
if(a>b)then exit(a) else exit(b);
end;
procedure pushdown(k:longint);
begin
if(k=0)then exit;
if(t[k].rev=1)then
begin
if(t[k].ch[0]<>0)then t[t[k].ch[0]].rev:=t[t[k].ch[0]].rev xor 1;
if(t[k].ch[1]<>0)then t[t[k].ch[1]].rev:=t[t[k].ch[1]].rev xor 1;
swap(t[k].ch[0],t[k].ch[1]);swap(t[k].lmax,t[k].rmax);
t[k].rev:=0;
end;
if(t[k].same<>INF)then
begin
if(t[k].ch[0]<>0)then t[t[k].ch[0]].same:=t[k].same;
if(t[k].ch[1]<>0)then t[t[k].ch[1]].same:=t[k].same;
t[k].v:=t[k].same;
t[k].sum:=t[k].same*t[k].sz;
if(t[k].same<0)then begin t[k].mmax:=t[k].v;t[k].lmax:=t[k].v;t[k].rmax:=t[k].v end
else begin t[k].mmax:=t[k].sum;t[k].lmax:=t[k].sum;t[k].rmax:=t[k].sum end;
t[k].same:=INF;
end;
end;
procedure pushup(k:longint);
var l,r:longint;
begin
if(k=0)then exit;
l:=t[k].ch[0];r:=t[k].ch[1];
pushdown(k);pushdown(l);pushdown(r);
t[k].sz:=1+t[l].sz+t[r].sz;
t[k].sum:=t[k].v+t[l].sum+t[r].sum;
t[k].mmax:=-INF;t[k].lmax:=-INF;t[k].rmax:=-INF;
if(l<>0)then t[k].lmax:=max(t[k].lmax,t[l].lmax);
if(r<>0)then t[k].lmax:=max(t[k].lmax,t[l].sum+t[k].v+t[r].lmax);
t[k].lmax:=max(t[k].lmax,t[l].sum+t[k].v);
if(r<>0)then t[k].rmax:=max(t[k].rmax,t[r].rmax);
if(l<>0)then t[k].rmax:=max(t[k].rmax,t[r].sum+t[k].v+t[l].rmax);
t[k].rmax:=max(t[k].rmax,t[r].sum+t[k].v);
if(l<>0)then t[k].mmax:=max(t[k].mmax,t[l].mmax);
if(r<>0)then t[k].mmax:=max(t[k].mmax,t[r].mmax);
t[k].mmax:=max(t[k].mmax,max(0,t[l].rmax)+t[k].v+max(0,t[r].lmax));
end;
function cmp(x,k:longint):longint;
begin
if(t[x].ch[0]=k)then exit(0) else exit(1);
end;
procedure rotate(k,c:longint);
var x:longint;
begin
x:=t[k].f;
pushdown(x);pushdown(k);
t[x].ch[c xor 1]:=t[k].ch[c];t[t[k].ch[c]].f:=x;t[k].ch[c]:=x;
t[k].f:=t[x].f;
if(t[x].f<>0)then t[t[x].f].ch[cmp(t[x].f,x)]:=k;
t[x].f:=k;
pushup(x);
end;
procedure splay(k,goal:longint);
var x,y,f1,f2:longint;
begin
pushdown(k);
while(t[k].f<>goal)do
begin
x:=t[k].f;y:=t[x].f;
if(y=goal)then rotate(k,cmp(x,k)xor 1)
else begin
f1:=cmp(y,x);f2:=cmp(x,k);
if(f1=f2)then begin rotate(x,f1 xor 1);rotate(k,f1 xor 1) end
else begin rotate(k,f2 xor 1);rotate(k,f1 xor 1) end;
end;
end;
pushup(k);
if(goal=0)then root:=k;
end;
procedure rotateto(k,goal:longint);
var i:longint;
begin
i:=root;
pushdown(i);
while(t[t[i].ch[0]].sz<>k)do
begin
if(k0)then begin x:=st[tst];dec(tst) end
else begin inc(top);x:=top end;
t[x].ch[0]:=0;t[x].ch[1]:=0;
t[x].sz:=1;t[x].same:=INF;t[x].rev:=0;t[x].f:=f;
t[x].v:=k;t[x].mmax:=k;t[x].lmax:=k;t[x].rmax:=k;
end;
procedure maketree(var x:longint;l,r,f:longint);
var mid:longint;
begin
if(l>r)then exit;
mid:=(l+r)>>1;
newnode(x,f,a[mid]);
maketree(t[x].ch[0],l,mid-1,x);
maketree(t[x].ch[1],mid+1,r,x);
pushup(x);
end;
procedure readin(n:longint);
var i:longint;
begin
for i:=1 to n do read(a[i]);
readln;
maketree(t[t[root].ch[1]].ch[0],1,n,t[root].ch[1]);
end;
procedure init;
begin
tst:=0;
newnode(root,0,-INF);
newnode(t[root].ch[1],root,-INF);
readin(n);
pushup(t[root].ch[1]);pushup(root);
end;
procedure getchar;
var c:char;
begin
s:='';
read(c);
while(not eoln)and(c<>' ')do
begin
s:=s+c;read(c);
end;
if(c<>' ')then s:=s+c;
end;
procedure print(k:longint);
begin
if(k=0)then exit;
pushdown(k);
print(t[k].ch[0]);
writeln('node:',k,' lc:',t[k].ch[0],' rc:',t[k].ch[1],' f:',t[k].f,' sz:',t[k].sz,' v:',t[k].v,
' sum:',t[k].sum,' rev:',t[k].rev);
print(t[k].ch[1]);
end;
procedure debug;
begin
writeln;
writeln(root);
print(root);
writeln;
end;
begin
//assign(input,'sequence.in');reset(input);
//assign(output,'sequence.out');rewrite(output);
readln(n,m);
init;
for i:=1 to m do
begin
// writeln('==========',i,'=========');
getchar;
if(s='INSERT')then
begin
read(p,tot);rotateto(p,0);rotateto(p+1,root);readin(tot);
end;
if(s='DELETE')then
begin
readln(p,tot);
rotateto(p-1,0);rotateto(p+tot,root);
del(t[t[root].ch[1]].ch[0]);t[t[root].ch[1]].ch[0]:=0;
end;
if(s='MAKE-SAME')then
begin
readln(p,tot,x);
rotateto(p-1,0);rotateto(p+tot,root);
t[t[t[root].ch[1]].ch[0]].same:=x;
end;
if(s='REVERSE')then
begin
readln(p,tot);
rotateto(p-1,0);rotateto(p+tot,root);
t[t[t[root].ch[1]].ch[0]].rev:=t[t[t[root].ch[1]].ch[0]].rev xor 1;
end;
if(s='GET-SUM')then
begin
readln(p,tot);
rotateto(p-1,0);rotateto(p+tot,root);
writeln(t[t[t[root].ch[1]].ch[0]].sum);
end;
if(s='MAX-SUM')then
begin
readln;writeln(t[root].mmax);
end;
pushup(t[root].ch[1]);pushup(root);
end;
//close(input);close(output);
end.
推荐一下squarefk大神的代码
#include
#include
#include
#define REP(i,n) for (int i=1;i<=n;++i)
using namespace std;
const int INF=1999999999,MAXN=500050;
struct TTTT{int sam,rev,num,size,sum,s0,s1,s2,s[2],p;} t[MAXN];
void Sets(int p,int k,int d) {if (t[p].s[d]=k) t[k].p=p;}
int Which(int k) {return t[t[k].p].s[1]==k;}
int n,m,x,k,top,root,a[MAXN],st[MAXN];
char s[11];
void Pushdown(int k) {
if (t[k].rev) {
if (t[k].s[0]) t[t[k].s[0]].rev^=1;
if (t[k].s[1]) t[t[k].s[1]].rev^=1;
swap(t[k].s[0],t[k].s[1]);
swap(t[k].s0,t[k].s1);
t[k].rev=0;
}
if (t[k].sam!=INF) {
if (t[k].s[0]) t[t[k].s[0]].sam=t[k].sam;
if (t[k].s[1]) t[t[k].s[1]].sam=t[k].sam;
t[k].num=t[k].sam;
t[k].sum=t[k].size*t[k].num;
if (t[k].num<0) t[k].s0=t[k].s1=t[k].s2=t[k].num;
else t[k].s0=t[k].s1=t[k].s2=t[k].num*t[k].size;
t[k].sam=INF;
}
}
void Relax(int &a,int b) {if (b>a) a=b;}
void Update(int k) {
Pushdown(k);
Pushdown(t[k].s[0]);
Pushdown(t[k].s[1]);
t[k].size=t[t[k].s[0]].size+t[t[k].s[1]].size+1;
t[k].sum=t[t[k].s[0]].sum+t[t[k].s[1]].sum+t[k].num;
t[k].s0=t[k].s1=t[k].s2=-INF;
if (t[k].s[0]) Relax(t[k].s0,t[t[k].s[0]].s0);
if (t[k].s[1]) Relax(t[k].s0,t[t[k].s[0]].sum+t[k].num+t[t[k].s[1]].s0);
Relax(t[k].s0,t[t[k].s[0]].sum+t[k].num);
if (t[k].s[1]) Relax(t[k].s1,t[t[k].s[1]].s1);
if (t[k].s[0]) Relax(t[k].s1,t[t[k].s[1]].sum+t[k].num+t[t[k].s[0]].s1);
Relax(t[k].s1,t[t[k].s[1]].sum+t[k].num);
if (t[k].s[0]) Relax(t[k].s2,t[t[k].s[0]].s2);
if (t[k].s[1]) Relax(t[k].s2,t[t[k].s[1]].s2);
Relax(t[k].s2,max(0,t[t[k].s[0]].s1)+max(0,t[t[k].s[1]].s0)+t[k].num);
}
void Rot(int k) {
int p=t[k].p,d=Which(k);
Sets(p,t[k].s[d^1],d);
if (!t[p].p) t[root=k].p=0;
else Sets(t[p].p,k,Which(p));
Sets(k,p,d^1);
Update(p);
}
void Splay(int k,int goal) {
while (t[k].p!=goal) {
if (t[t[k].p].p==goal) Rot(k);
else
if (Which(k)==Which(t[k].p))
{Rot(t[k].p);Rot(k);}
else
{Rot(k);Rot(k);}
}
Update(k);
}
int Get() {
char c=getchar(); int ret=0;
while ((c!='-')&&((c<'0')||(c>'9'))) c=getchar();
if (c=='-') return -Get();
while ((c>='0')&&(c<='9')) ret=ret*10+c-'0',c=getchar();
return ret;
}
int New(int num) {
int k=st[top--];
t[k].size=1; t[k].rev=0; t[k].sam=INF;
t[k].num=t[k].sum=t[k].s0=t[k].s1=t[k].s2=num;
return k;
}
void Del(int k) {
if (!k) return;
st[++top]=k;
Del(t[k].s[0]);
Del(t[k].s[1]);
}
int Build(int l,int r) {
if (l>r) return 0;
int m=(l+r)>>1;
int k=New(a[m]);
t[k].s[0]=Build(l,m-1); Sets(k,t[k].s[0],0);
t[k].s[1]=Build(m+1,r); Sets(k,t[k].s[1],1);
Update(k);
return k;
}
int Find(int x) {
int k=root;
for (;;) {
Pushdown(k);
if (x==t[t[k].s[0]].size+1) break;
if (x