SPOJ GSS系列
2016-01-08 20:59
459 查看
这个系列基本包括了线段树的所有经典案例,把这个做完线段树的基本操作就可以了,,,,当年怎么没人告诉我QAQAQAQ
w[a,3]:该区间最大子段和
w[a,4]:该区间含左端点的最大子段和
w[a,5]:该区间含右端点的最大子段和
pushup的话自己yy一下就好了
当L1<=R1<=L2<=R2时sum[R1+1..L2−1]肯定是取的在[L1,R1]取最大右端点和[L2,R2]取最大左端点L_1<=R_1<=L_2<=R_2时sum[R_1+1..L_2-1]肯定是取的在[L_1,R_1]取最大右端点和[L_2,R_2]取最大左端点
当L1<=L2<=R1<=R2时L_1<=L_2<=R_1<=R_2时
L在[L1,L2]时L在[L_1,L_2]时
R在[L2,R1]时:[L1,L2]最大右端点+[L2,R1]最大左端点R在[L_2,R_1]时:[L_1,L_2]最大右端点+[L_2,R_1]最大左端点
R在[R1,R2]时:[L1,L2]最大右端点+sum[L2,R1]+[R1,R2]最大左端点R在[R_1,R_2]时:[L_1,L_2]最大右端点+sum[L_2,R_1]+[R_1,R_2]最大左端点
L在[L2,R1]时L在[L_2,R_1]时
R在[L2,R1]时:[L2,R1]最大子段和R在[L_2,R_1]时:[L_2,R_1]最大子段和
R在[R1,R2]时:[L2,R1]最大右端点+[R1,R2]最大左端点R在[R_1,R_2]时:[L_2,R_1]最大右端点+[R_1,R_2]最大左端点
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/题目大意
查询起点在[L1,R1]终点在[L2,R2]的最大子段和查询起点在[L_1,R_1]终点在[L_2,R_2]的最大子段和题解
分类讨论当L1<=R1<=L2<=R2时sum[R1+1..L2−1]肯定是取的在[L1,R1]取最大右端点和[L2,R2]取最大左端点L_1<=R_1<=L_2<=R_2时sum[R_1+1..L_2-1]肯定是取的在[L_1,R_1]取最大右端点和[L_2,R_2]取最大左端点
当L1<=L2<=R1<=R2时L_1<=L_2<=R_1<=R_2时
L在[L1,L2]时L在[L_1,L_2]时
R在[L2,R1]时:[L1,L2]最大右端点+[L2,R1]最大左端点R在[L_2,R_1]时:[L_1,L_2]最大右端点+[L_2,R_1]最大左端点
R在[R1,R2]时:[L1,L2]最大右端点+sum[L2,R1]+[R1,R2]最大左端点R在[R_1,R_2]时:[L_1,L_2]最大右端点+sum[L_2,R_1]+[R_1,R_2]最大左端点
L在[L2,R1]时L在[L_2,R_1]时
R在[L2,R1]时:[L2,R1]最大子段和R在[L_2,R_1]时:[L_2,R_1]最大子段和
R在[R1,R2]时:[L2,R1]最大右端点+[R1,R2]最大左端点R在[R_1,R_2]时:[L_2,R_1]最大右端点+[R_1,R_2]最大左端点
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.
相关文章推荐
- 【慕课笔记】第二章 变量和常量 第3节 变量是什么
- HTML简单总结
- 变量小随笔
- 二维码高亮
- 作用域+链接属性+存储类型
- Qt模块化笔记之Qt_Quick——用QQuickImageProvider给Image组件添加图片
- HDU1392:Surround the Trees(凸包问题)
- 填算式
- 享元模式 c#
- mysql的字符集和整理是怎么一回事
- 猜生日
- Leetcode225: Candy
- BZOJ 4393: [Usaco2015]Fruit Feast|离散化|暴力
- 求21位数的水仙花数
- 9patch
- Codeforces Contest #338 Div.2
- 给Layer添加触摸事件
- activity之间传递对象的两种方式
- 《Java虚拟机原理图解》4.JVM机器指令集
- Affinity Photo 图层面板消失的解决办法