SPOJ GSS系列

这个系列基本包括了线段树的所有经典案例,把这个做完线段树的基本操作就可以了,,,,当年怎么没人告诉我QAQAQAQ

GSS1 - Can you answer these queries I

传送门

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.

GSS2 - Can you answer these queries II

传送门

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.

GSS3 - Can you answer these queries III

传送门

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.

GSS4 - Can you answer these queries IV

传送门

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.

GSS5 - Can you answer these queries V

传送门

http://www.spoj.com/problems/GSS5/

题目大意

[L1R1][L2R2]

题解

分类讨论
L1<=R1<=L2<=R2sum[R1+1..L21][L1R1][L2R2]
L1<=L2<=R1<=R2

  • L[L1,L2]

    • R[L2,R1]:[L1,L2]+[L2,R1]
    • R[R1,R2]:[L1,L2]+sum[L2,R1]+[R1,R2]
  • L[L2,R1]

    • R[L2,R1]:[L2,R1]
    • R[R1,R2]:[L2,R1]+[R1,R2]
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.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值