UVa 3938 "Ray, Pass me the dishes!"
2014-11-08 16:36
453 查看
题意:给一个长度为n的序列D,对m个询问做出回答。对于询问(a,b),需要找到两个下标x,y,使得a<=x<=y<=b,并且Dx~Dy的和尽量大。如果有多解,x应该尽量小,如果还有多解,y应该尽量小。
思路:线段树。每个节点维护这些内容:区间和,区间的最大子段和,最大前后缀和,最大子段和以及它们的下标。查询直接返回一个区间节点,建树时的节点合并其实和查询时的节点合并是一样的。
照着大白书写了这题,感觉思路大为开阔~
思路:线段树。每个节点维护这些内容:区间和,区间的最大子段和,最大前后缀和,最大子段和以及它们的下标。查询直接返回一个区间节点,建树时的节点合并其实和查询时的节点合并是一样的。
照着大白书写了这题,感觉思路大为开阔~
#include<cstdio> #include<iostream> #include<algorithm> #include<string.h> #include<math.h> using namespace std; #define maxn 500010 #define ll long long struct node{ ll sum; ll max_sub; ll max_suffix; ll max_prefix; int subl,subr; int sl,pr; int l; int r; }; node tree[maxn*4]; int build_tree(int n,int l,int r){ tree .l=l; tree .r=r; if(l==r){ int t; scanf("%d",&t); tree .sum=tree .max_sub=tree .max_prefix=tree .max_suffix=t; tree .subl=tree .subr=tree .sl=tree .pr=l; }else{ int mid=(l+r)/2; build_tree(n*2,l,mid); build_tree(n*2+1,mid+1,r); tree .sum=tree[n*2].sum+tree[n*2+1].sum; if(tree[n*2].sum+tree[n*2+1].max_prefix > tree[n*2].max_prefix){ tree .max_prefix=tree[n*2].sum+tree[n*2+1].max_prefix; tree .pr=tree[n*2+1].pr; }else{ tree .max_prefix=tree[n*2].max_prefix; tree .pr=tree[n*2].pr; } if(tree[n*2+1].max_suffix > tree[n*2+1].sum+tree[n*2].max_suffix ){ tree .max_suffix = tree[n*2+1].max_suffix; tree .sl=tree[n*2+1].sl; }else{ tree .max_suffix = tree[n*2+1].sum+tree[n*2].max_suffix; tree .sl=tree[n*2].sl; } ll tmp[3]; tmp[0]=tree[n*2].max_sub; tmp[1]=tree[n*2].max_suffix+tree[n*2+1].max_prefix; tmp[2]=tree[n*2+1].max_sub; sort(tmp,tmp+3); tree .max_sub=tmp[2]; if(tmp[2]==tree[n*2].max_sub){ tree .subl=tree[n*2].subl; tree .subr=tree[n*2].subr; }else if(tmp[2]==tree[n*2].max_suffix+tree[n*2+1].max_prefix){ tree .subl=tree[n*2].sl; tree .subr=tree[n*2+1].pr; }else{ tree .subl=tree[n*2+1].subl; tree .subr=tree[n*2+1].subr; } } } node query(int n,int l,int r){ node re; if(tree .l==l&&tree .r==r){ re=tree ; return re; } int mid=(tree .l+tree .r)/2; if(r<=mid){ return query(n*2,l,r); }else{ if(l>mid){ return query(n*2+1,l,r); }else{ node nl=query(n*2,l,mid); node nr=query(n*2+1,mid+1,r); if(nl.sum+nr.max_prefix > nl.max_prefix){ re.max_prefix=nl.sum+nr.max_prefix; re.pr=nr.pr; }else{ re.max_prefix=nl.max_prefix; re.pr=nl.pr; } if(nr.max_suffix > nr.sum+nl.max_suffix ){ re.max_suffix = nr.max_suffix; re.sl=nr.sl; }else{ re.max_suffix = nr.sum+nl.max_suffix; re.sl=nl.sl; } ll tmp[3]; tmp[0]=nl.max_sub; tmp[1]=nl.max_suffix+nr.max_prefix; tmp[2]=nr.max_sub; sort(tmp,tmp+3); re.max_sub=tmp[2]; if(tmp[2]==nl.max_sub){ re.subl=nl.subl; re.subr=nl.subr; }else if(tmp[2]==nl.max_suffix+nr.max_prefix){ re.subl=nl.sl; re.subr=nr.pr; }else{ re.subl=nr.subl; re.subr=nr.subr; } return re; } } } int main(){ int n,m; int cas=0; while(cin>>n>>m){ cas++; build_tree(1,1,n); printf("Case %d:\n",cas); for(int i=1;i<=m;i++){ int l,r; scanf("%d%d",&l,&r); node ans=query(1,l,r); printf("%d %d\n",ans.subl,ans.subr); } } return 0; }
相关文章推荐
- 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!" 解题报告
- UVALive - 3938:"Ray, Pass me the dishes!"
- UVA1400 - "Ray, Pass me the dishes!"
- uva 1400 "Ray, Pass me the dishes!" 线段树
- LA 3938 "Ray, Pass me the dishes!" / 线段树单点更新
- UVA live 3938 - "Ray, Pass me the dishes!"(线段树)
- UVaLive 3938 "Ray, Pass me the dishes!" (线段树求动态最大连续和)
- UVALive 3938 "Ray, Pass me the dishes!"
- Uva 1400 "Ray, Pass me the dishes!" (线段树 区间合并)
- UVA 1400 1400 - "Ray, Pass me the dishes!"(线段树)
- UVALive3938 "Ray, Pass me the dishes!" 线段树动态区间最大和
- UVALive 3938 "Ray, Pass me the dishes!"
- Regionals 2007 >> Asia - Nanjing - "Ray, Pass me the dishes!" 线段树 难 uva live 3938
- UVALive3938 "Ray, Pass me the dishes!" 线段树动态区间最大和
- UVA - 1400"Ray, Pass me the dishes!"(线段树)
- UvaLA 3938 "Ray, Pass me the dishes!"
- uva 1400 "Ray, Pass me the dishes!"