这个系列基本包括了线段树的所有经典案例,把这个做完线段树的基本操作就可以了,,,,当年怎么没人告诉我QAQAQAQ
http://www.spoj.com/problems/GSS1/
给定序列,询问区间[L,R]内的最大子段和
线段合并基本操作,每个区间记录
w[a,3]:该区间最大子段和
w[a,4]:该区间含左端点的最大子段和
w[a,5]:该区间含右端点的最大子段和
pushup的话自己yy一下就好了
const
maxn=50005;
type
mm=record
mx,mxl,mxr:longint; end;
var
w:array[0..4*maxn,1..5]of longint;
sum:array[0..maxn]of longint;
i,j,k:longint;
n,m,a,b,c:longint;
function max(a,b:longint):longint;
begin if a>b then exit(a) else exit(b); end;
procedure pushup(a:longint);
begin
if w[a,1]=w[a,2] then exit;
w[a,3]:=max(max(w[a<<1,3],w[a<<1+1,3]),w[a<<1,5]+w[a<<1+1,4]);
w[a,4]:=max(w[a<<1,4],sum[w[a<<1,2]]-sum[w[a<<1,1]-1]+w[a<<1+1,4]);
w[a,5]:=max(w[a<<1+1,5],sum[w[a<<1+1,2]]-sum[w[a<<1+1,1]-1]+w[a<<1,5]);
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r;
if l=r then begin read(w[a,3]); w[a,4]:=w[a,3]; w[a,5]:=w[a,3]; sum[l]:=sum[l-1]+w[a,3]; exit; end;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
pushup(a);
end;
function query(a,l,r:longint):mm;
var mid:longint; tt,tt1,tt2:mm;
begin
if (w[a,1]=l)and(w[a,2]=r) then begin tt.mx:=w[a,3]; tt.mxl:=w[a,4]; tt.mxr:=w[a,5]; exit(tt); end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then exit(query(a<<1,l,r)) else
if l>mid then exit(query(a<<1+1,l,r))
else begin
tt1:=query(a<<1,l,mid); tt2:=query(a<<1+1,mid+1,r);
tt.mx:=max(max(tt1.mx,tt2.mx),tt1.mxr+tt2.mxl);
tt.mxl:=max(tt1.mxl,sum[mid]-sum[l-1]+tt2.mxl);
tt.mxr:=max(tt2.mxr,sum[r]-sum[mid]+tt1.mxr);
exit(tt);
end;
end;
begin
readln(n); sum[0]:=0;
build(1,1,n);
readln(m);
for i:=1 to m do
begin
readln(a,b);
writeln(query(1,a,b).mx);
end;
end.
http://www.spoj.com/problems/GSS2/
给定序列,查询[L,R]内最大子段和,相同的数只贡献一次
经典的离线操作,HH的项链
const
maxn=100005;
type
mm=record
mx,mxl,mxr,sum:longint; end;
var
w:array[0..4*maxn,1..6]of longint;
x:array[0..maxn,1..3]of longint;
y:array[-maxn..maxn]of longint;
ans,t,z:array[0..maxn]of longint;
i,j,k:longint;
n,m,a,b:longint;
procedure sort(l,r:longint);
var i,j,a,b,c:longint;
begin
i:=l; j:=r; a:=x[(l+r)>>1,1]; c:=x[(l+r)>>1,2];
repeat
while (x[i,1]<a)or((x[i,1]=a)and(x[i,2]<c)) do inc(i);
while (a<x[j,1])or((x[j,1]=a)and(x[j,2]>c)) do dec(j);
if not(i>j) then
begin
b:=x[i,1]; x[i,1]:=x[j,1]; x[j,1]:=b;
b:=x[i,2]; x[i,2]:=x[j,2]; x[j,2]:=b;
b:=x[i,3]; x[i,3]:=x[j,3]; x[j,3]:=b;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure pushup(a:longint);
begin
if w[a,1]=w[a,2] then exit;
w[a,3]:=max(max(w[a<<1,3],w[a<<1+1,3]),w[a<<1,5]+w[a<<1+1,4]);
w[a,4]:=max(w[a<<1,4],w[a<<1,6]+w[a<<1+1,4]);
w[a,5]:=max(w[a<<1+1,5],w[a<<1+1,6]+w[a<<1,5]);
w[a,6]:=w[a<<1,6]+w[a<<1+1,6];
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r; w[a,3]:=-maxn; w[a,4]:=-maxn; w[a,5]:=-maxn; w[a,6]:=-maxn;
if l=r then exit;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
end;
procedure update(a,b,c:longint);
var mid:longint;
begin
if w[a,1]=w[a,2] then begin w[a,3]:=c; w[a,4]:=c; w[a,5]:=c; w[a,6]:=c; exit; end;
mid:=(w[a,1]+w[a,2])>>1;
if b<=mid then update(a<<1,b,c) else update(a<<1+1,b,c);
pushup(a);
end;
function query(a,l,r:longint):mm;
var mid:longint; tt,tt1,tt2:mm;
begin
if (w[a,1]=l)and(w[a,2]=r) then begin tt.mx:=w[a,3]; tt.mxl:=w[a,4]; tt.mxr:=w[a,5]; tt.sum:=w[a,6]; exit(tt); end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then exit(query(a<<1,l,r)) else
if l>mid then exit(query(a<<1+1,l,r))
else begin
tt1:=query(a<<1,l,mid); tt2:=query(a<<1+1,mid+1,r);
tt.mx:=max(max(tt1.mx,tt2.mx),tt1.mxr+tt2.mxl);
tt.mxl:=max(tt1.mxl,tt1.sum+tt2.mxl);
tt.mxr:=max(tt2.mxr,tt2.sum+tt1.mxr);
tt.sum:=tt1.sum+tt2.sum;
exit(tt);
end;
end;
begin
readln(n);
build(1,1,n);
for i:=1 to n do
read(t[i]);
for i:=1 to n do
begin
a:=t[i];
if y[a]=0 then update(1,i,a) else z[y[a]]:=i;
y[a]:=i;
end;
readln(m);
for i:=1 to m do
begin
readln(x[i,1],x[i,2]);
x[i,3]:=i;
end;
sort(1,m); x[0,1]:=1;
for i:=1 to m do
begin
for j:=x[i-1,1] to x[i,1]-1 do
begin
update(1,j,0);
if z[j]<>0 then update(1,z[j],t[j]);
end;
ans[x[i,3]]:=query(1,x[i,1],x[i,2]).mx;
end;
for i:=1 to m do
if ans[i]<0
then writeln(0)
else writeln(ans[i]);
end.
http://www.spoj.com/problems/GSS3/
单点修改+查询区间最大子段和
同GSS1,单点修改,,,
const
maxn=100005;
type
mm=record
mx,mxl,mxr,sum:longint; end;
var
w:array[0..4*maxn,1..6]of longint;
i,j,k:longint;
n,m,a,b,c:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure pushup(a:longint);
begin
if w[a,1]=w[a,2] then exit;
w[a,3]:=max(max(w[a<<1,3],w[a<<1+1,3]),w[a<<1,5]+w[a<<1+1,4]);
w[a,4]:=max(w[a<<1,4],w[a<<1,6]+w[a<<1+1,4]);
w[a,5]:=max(w[a<<1+1,5],w[a<<1+1,6]+w[a<<1,5]);
w[a,6]:=w[a<<1,6]+w[a<<1+1,6];
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r;
if l=r then begin read(w[a,3]); w[a,4]:=w[a,3]; w[a,5]:=w[a,3]; w[a,6]:=w[a,3]; exit; end;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
pushup(a);
end;
procedure update(a,b,c:longint);
var mid:longint;
begin
if w[a,1]=w[a,2] then begin w[a,3]:=c; w[a,4]:=c; w[a,5]:=c; w[a,6]:=c; exit; end;
mid:=(w[a,1]+w[a,2])>>1;
if b<=mid then update(a<<1,b,c) else update(a<<1+1,b,c);
pushup(a);
end;
function query(a,l,r:longint):mm;
var mid:longint; tt,tt1,tt2:mm;
begin
if (w[a,1]=l)and(w[a,2]=r) then begin tt.mx:=w[a,3]; tt.mxl:=w[a,4]; tt.mxr:=w[a,5]; tt.sum:=w[a,6]; exit(tt); end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then exit(query(a<<1,l,r)) else
if l>mid then exit(query(a<<1+1,l,r))
else begin
tt1:=query(a<<1,l,mid); tt2:=query(a<<1+1,mid+1,r);
tt.mx:=max(max(tt1.mx,tt2.mx),tt1.mxr+tt2.mxl);
tt.mxl:=max(tt1.mxl,tt1.sum+tt2.mxl);
tt.mxr:=max(tt2.mxr,tt2.sum+tt1.mxr);
tt.sum:=tt1.sum+tt2.sum;
exit(tt);
end;
end;
begin
readln(n);
build(1,1,n);
readln(m);
for i:=1 to m do
begin
readln(a,b,c);
if a=0
then update(1,b,c)
else writeln(query(1,b,c).mx);
end;
end.
http://www.spoj.com/problems/GSS4/
区间开根号+区间和查询
没啥说的….
const
maxn=100005;
var
w:array[0..4*maxn,1..3]of int64;
i,j,k:longint;
n,m,a,b,c,d,t:longint;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r;
if l=r then begin read(w[a,3]); exit; end;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
w[a,3]:=w[a<<1,3]+w[a<<1+1,3];
end;
procedure update(a,l,r:longint);
var mid:longint;
begin
if w[a,3]<=w[a,2]-w[a,1]+1 then exit;
if w[a,1]=w[a,2] then begin w[a,3]:=trunc(sqrt(w[a,3])); exit; end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then update(a<<1,l,r) else
if l>mid then update(a<<1+1,l,r)
else begin update(a<<1,l,mid); update(a<<1+1,mid+1,r); end;
w[a,3]:=w[a<<1,3]+w[a<<1+1,3];
end;
function query(a,l,r:longint):int64;
var mid:longint;
begin
if (w[a,1]=l)and(w[a,2]=r) then exit(w[a,3]);
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then exit(query(a<<1,l,r)) else
if l>mid then exit(query(a<<1+1,l,r))
else exit(query(a<<1,l,mid)+query(a<<1+1,mid+1,r));
end;
begin
t:=0;
while not eof do
begin
inc(t); writeln('Case #',t,':');
fillchar(w,sizeof(w),0);
readln(n);
build(1,1,n);
readln(m);
for i:=1 to m do
begin
readln(a,b,c); if b>c then begin d:=b; b:=c; c:=d; end;
if a=0
then update(1,b,c)
else writeln(query(1,b,c));
end;
end;
end.
http://www.spoj.com/problems/GSS5/
查询起点在[L1,R1]终点在[L2,R2]的最大子段和
分类讨论
当 L1<=R1<=L2<=R2时sum[R1+1..L2−1]肯定是取的在[L1,R1]取最大右端点和[L2,R2]取最大左端点
当 L1<=L2<=R1<=R2时
L在[L1,L2]时
L在[L2,R1]时
const
maxn=10005;
type
mm=record
mx,mxl,mxr,sum:longint; end;
var
w:array[0..4*maxn,1..6]of longint;
i,j,k,l:longint;
n,m,t,a,b,c,d,ans,ans1,ans2,ans3:longint;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure pushup(a:longint);
begin
if w[a,1]=w[a,2] then exit;
w[a,3]:=max(max(w[a<<1,3],w[a<<1+1,3]),w[a<<1,5]+w[a<<1+1,4]);
w[a,4]:=max(w[a<<1,4],w[a<<1,6]+w[a<<1+1,4]);
w[a,5]:=max(w[a<<1+1,5],w[a<<1+1,6]+w[a<<1,5]);
w[a,6]:=w[a<<1,6]+w[a<<1+1,6];
end;
procedure build(a,l,r:longint);
var mid:longint;
begin
w[a,1]:=l; w[a,2]:=r;
if l=r then begin read(w[a,3]); w[a,4]:=w[a,3]; w[a,5]:=w[a,3]; w[a,6]:=w[a,3]; exit; end;
mid:=(l+r)>>1;
build(a<<1,l,mid); build(a<<1+1,mid+1,r);
pushup(a);
end;
function query(a,l,r:longint):mm;
var mid:longint; tt,tt1,tt2:mm;
begin
tt.mx:=0; tt.mxr:=0; tt.mxl:=0; tt.sum:=0;
if l>r then exit(tt);
if (w[a,1]=l)and(w[a,2]=r) then begin tt.mx:=w[a,3]; tt.mxl:=w[a,4]; tt.mxr:=w[a,5]; tt.sum:=w[a,6]; exit(tt); end;
mid:=(w[a,1]+w[a,2])>>1;
if r<=mid then exit(query(a<<1,l,r)) else
if l>mid then exit(query(a<<1+1,l,r))
else begin
tt1:=query(a<<1,l,mid); tt2:=query(a<<1+1,mid+1,r);
tt.mx:=max(max(tt1.mx,tt2.mx),tt1.mxr+tt2.mxl);
tt.mxl:=max(tt1.mxl,tt1.sum+tt2.mxl);
tt.mxr:=max(tt2.mxr,tt2.sum+tt1.mxr);
tt.sum:=tt1.sum+tt2.sum;
exit(tt);
end;
end;
begin
readln(t);
for l:=1 to t do
begin
fillchar(w,sizeof(w),0);
read(n); build(1,1,n);
readln(m);
for i:=1 to m do
begin
readln(a,b,c,d);
if b<c
then begin
ans:=query(1,b,c).sum;
if b-1>=a then inc(ans,max(0,query(1,a,b-1).mxr));
if c+1<=d then inc(ans,max(0,query(1,c+1,d).mxl));
end
else begin
ans1:=query(1,c,c).sum;
if a+1<=c then inc(ans1,max(0,query(1,a,c-1).mxr));
if c+1<=d then inc(ans1,max(0,query(1,c+1,d).mxl));
ans2:=query(1,b,b).sum;
if a+1<=b then inc(ans2,max(0,query(1,a,b-1).mxr));
if b+1<=d then inc(ans2,max(0,query(1,b+1,d).mxl));
ans3:=query(1,c,b).mx;
ans:=max(max(ans1,ans2),ans3);
end;
writeln(ans);
end;
end;
end.