LA 3938 - "Ray, Pass me the dishes!"(线段树)
动态最大连续和。
思路:完全参照刘汝佳厚书的思路。
几天前,就从书上得到一个思路,却不知怎么实现,于是乎,几天来一直广搜结题报告,结合人家现成的代码,今天写成了代码,又调了半下午的bug,终于ac了。
构造一课线段树,其中每个节点维护3个信息,最大连续和(x,y),最大前缀和(pre),最大后缀和(suf),虽然都叫做什么什么和,存的却都是位置标记,
1、建树
2、若干次查询
这道题目没有加入树节点的修改,算是数据结构中的基础题了。
思路来自于静态最大连续和的求解,(最大连续和或在[1...m],或在[m+1......n],或在[x...m......y])
代码如下:
#include <cstdio> #include <algorithm> using namespace std; #define M 500005 struct Node{ int x, y, pre, suf, subx, suby; }; int n, m; long long a[M], sum[M]; Node tree[2*M+10]; void creat(int x, int y, int o) { if(x==y) { tree[o].x = x; tree[o].y = x; tree[o].pre = x; tree[o].suf = x; tree[o].subx = x; tree[o].suby = x; return; } int m = (x+y)/2; creat(x, m, 2*o); creat(m+1, y, 2*o+1); tree[o].x = x; tree[o].y = y; tree[o].pre = sum[tree[2*o].pre]-sum[x-1] >= sum[tree[2*o+1].pre]-sum[x-1] ? tree[2*o].pre : tree[2*o+1].pre; tree[o].suf = sum[y]-sum[tree[2*o].suf-1] >= sum[y]-sum[tree[2*o+1].suf-1] ? tree[2*o].suf : tree[2*o+1].suf; if(sum[tree[2*o].suby]-sum[tree[2*o].subx-1]>=sum[tree[2*o+1].suby]-sum[tree[2*o+1].subx-1]) { tree[o].suby = tree[2*o].suby; tree[o].subx = tree[2*o].subx; } else { tree[o].suby = tree[2*o+1].suby; tree[o].subx = tree[2*o+1].subx; } if(sum[tree[2*o+1].pre]-sum[tree[2*o].suf-1] > sum[tree[o].suby]-sum[tree[o].subx-1]) { tree[o].subx = tree[2*o].suf; tree[o].suby = tree[2*o+1].pre; } else if(sum[tree[2*o+1].pre]-sum[tree[2*o].suf-1] == sum[tree[o].suby]-sum[tree[o].subx-1]) { if(tree[o].subx > tree[2*o].suf||(tree[o].subx == tree[2*o].suf && tree[o].suby > tree[2*o+1].pre)) { tree[o].subx = tree[2*o].suf; tree[o].suby = tree[2*o+1].pre; } } } void buildtree() { creat(1,n,1); } void query(int o, int ql, int qr, int &ansx, int &ansy, int &pre, int &suf) { int x = tree[o].x, y = tree[o].y; if(ql<=x&&qr>=y) { ansx = tree[o].subx; ansy = tree[o].suby; pre = tree[o].pre; suf = tree[o].suf; return ; } int mid = (x+y)/2; if(qr<=mid) query(2*o,ql,qr,ansx,ansy,pre,suf); else if(ql>mid) query(2*o+1,ql,qr,ansx,ansy,pre,suf); else { int x1, x2, y1, y2,p1,p2,s1,s2; query(2*o,ql,mid,x1,y1,p1,s1); query(2*o+1,mid+1,qr,x2,y2,p2,s2); pre = sum[p1]-sum[ql-1] >= sum[p2]-sum[ql-1] ? p1 : p2 ; suf = sum[qr]-sum[s1-1] >= sum[qr]-sum[s2-1] ? s1 : s2 ; if(sum[y1]-sum[x1-1] >= sum[y2]-sum[x2-1]) { ansx = x1; ansy = y1; } else { ansx = x2; ansy = y2; } long long L = sum[m]-sum[s1-1]; long long R = sum[p2]-sum[m]; if(L+R > sum[ansy]-sum[ansx-1] || (L+R == sum[ansy]-sum[ansx-1] && ansx > s1) || (L+R == sum[ansy]-sum[ansx-1] && ansx == s1 && ansy > p2)) { ansx = s1; ansy = p2; } } } int main () { int k = 0; while(~scanf("%d %d",&n, &m)) { for(int i = 1; i <= n; ++i) { scanf("%lld",&a[i]); sum[i] = sum[i-1]+a[i]; } buildtree(); int ql, qr, ansx, ansy,pre,suf; printf("Case %d:\n",++k);//不要把case放错位置哦 while(m--) { scanf("%d %d",&ql, &qr); query(1, ql, qr, ansx, ansy,pre,suf); printf("%d %d\n", ansx, ansy); } } return 0; }