LA 3938 - "Ray, Pass me the dishes!"(线段树)
来源:互联网 发布:预测股票涨跌软件 编辑:程序博客网 时间:2024/05/22 14:23
动态最大连续和。
思路:完全参照刘汝佳厚书的思路。
几天前,就从书上得到一个思路,却不知怎么实现,于是乎,几天来一直广搜结题报告,结合人家现成的代码,今天写成了代码,又调了半下午的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 500005struct 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;}
- LA 3938 - "Ray, Pass me the dishes!"(线段树)
- LA 3938 "Ray, Pass me the dishes!"
- LA 3938 "Ray, Pass me the dishes!"
- LA 3938 "Ray, Pass me the dishes!" / 线段树单点更新
- UVA-1400 Ray, Pass me the Dishes, LA 3938 , 线段树,区间查询
- [线段树点修改]动态最大连续和(Ray,Pass me the Dishes, LA 3938)
- UVALive - 3938 "Ray, Pass me the dishes!" 线段树
- UVALive - 3938 "Ray, Pass me the dishes!" (线段树)
- uvalive 3938 Ray, Pass me the dishes!(线段树)
- LA-3938-"Ray, Pass me the dishes!" 解题报告
- UVA1400 "Ray, Pass me the dishes!" 线段树
- UVa Ray, Pass me the dishes! (线段树)
- UVA 1400 1400 - "Ray, Pass me the dishes!"(线段树)
- uva 1400 "Ray, Pass me the dishes!" 线段树
- uva 1400 - "Ray, Pass me the dishes!"(线段树)
- UVA - 1400"Ray, Pass me the dishes!"(线段树)
- LA3938 & UVA1400 - Ray, Pass me the dishes!(线段树)
- UVA 1400 "Ray, Pass me the dishes!" (线段树)
- 区分keydown和keypress事件
- 欧拉函数性质
- centos6.4最小安装版 pppoe上网配置 无线上网配置
- STL中的vector_map
- u-boot-2009.11在mini2440上的移植,关于SDRAM&NOR&NAND启动的几点疑惑
- LA 3938 - "Ray, Pass me the dishes!"(线段树)
- Binding之数据转换
- 汇编指令参考
- JNI的一个未解问题
- td文字超出设定宽度变成点
- newInstance()和new()
- java 如何得到文件的系统图标
- Mini2440 DM9000 驱动分析(一)
- Why do people hate Windows?