Live archive 3938 "Ray,Pass me the Dishes"
2016-08-24 20:51
381 查看
题意:给出一个长度为n的整数序列D,你的任务是对m个询问做出回答,对于询问(a,b),需要找到两个下标x,y使得a<=x<=y<=b并且使得Dx+Dx+1+……+Dy尽量大,如果有多组满足条件,应使x尽量小,如果还是有多解,y应该尽量小
这里要用线段树分治,一个连续和要么被包含在左儿子或者右儿子,要么跨越两个儿子,对于一个结点维护最大前缀和,后缀和,最大连续和。
题目要求输出区间,所以还要保存连续和最大的区间,以及前缀和,后缀和的位置。为了维护最大前缀和以及后缀和还需要一个区间和。
所以这道题写起来非常麻烦,但是思路还是 很清晰的
这里要用线段树分治,一个连续和要么被包含在左儿子或者右儿子,要么跨越两个儿子,对于一个结点维护最大前缀和,后缀和,最大连续和。
题目要求输出区间,所以还要保存连续和最大的区间,以及前缀和,后缀和的位置。为了维护最大前缀和以及后缀和还需要一个区间和。
所以这道题写起来非常麻烦,但是思路还是 很清晰的
#include<cstdio> #include<iostream> #define ls (r<<1) #define rs ((r<<1)+1) #define LL long long using namespace std; const int maxn=5e5+5; struct wk{ LL pre,suf,sub,sum; int l,r,pr,sl; }tree[maxn<<2]; int n,m,s[maxn]; int x,y; inline void _read(int &x){ char t=getchar();bool sign=true; while(t<'0'||t>'9') {if(t=='-')sign=false;t=getchar();} for(x=0;t>='0'&&t<='9';t=getchar())x=x*10+t-'0'; if(!sign)x=-x; } void updata(wk&u,wk&s1,wk&s2){ if(s1.pre>=s1.sum+s2.pre)u.pr=s1.pr,u.pre=s1.pre; else u.pr=s2.pr,u.pre=s1.sum+s2.pre; if(s2.suf<=s2.sum+s1.suf)u.sl=s1.sl,u.suf=s2.sum+s1.suf; else u.sl=s2.sl,u.suf=s2.suf; if(s1.sub>=s2.sub)u.l=s1.l,u.r=s1.r,u.sub=s1.sub; else u.l=s2.l,u.r=s2.r,u.sub=s2.sub; if(u.sub<s1.suf+s2.pre||(u.sub==s1.suf+s2.pre&&(u.l>s1.sl||(u.l==s1.sl&&u.r>s2.pr)))) u.sub=s1.suf+s2.pre,u.l=s1.sl,u.r=s2.pr; u.sum=s1.sum+s2.sum; } void build(int r,int L,int R){ if(L==R){ wk& u=tree[r]; u.pre=u.suf=u.sub=u.sum=s[L]; u.l=u.r=u.pr=u.sl=L; return; } int mid=(L+R)>>1; build(ls,L,mid); build(rs,mid+1,R); updata(tree[r],tree[ls],tree[rs]); } wk find(int r,int L,int R){ if(x<=L&&R<=y)return tree[r]; int mid=(L+R)>>1; wk ret; if(x<=mid&&mid<y){ wk a=find(ls,L,mid); wk b=find(rs,mid+1,R); updata(ret,a,b); return ret; } if(y<=mid) return find(ls,L,mid); return find(rs,mid+1,R); } int main(){ int kase=0; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=n;i++)_read(s[i]); build(1,1,n); printf("Case %d:\n",++kase); while(m--){ _read(x);_read(y); wk ans=find(1,1,n); printf("%d %d\n",ans.l,ans.r); } } }
相关文章推荐
- uvalive 3938 - "Ray, Pass me the dishes!" +动态最大连续和+线段树
- Regionals 2007 >> Asia - Nanjing - "Ray, Pass me the dishes!" 线段树 难 uva live 3938
- UVA live 3938 - "Ray, Pass me the dishes!"(线段树)
- UVALive - 3938 "Ray, Pass me the dishes!" 线段树
- UVALive - 3938 "Ray, Pass me the dishes!"
- UVaLive 3938 "Ray, Pass me the dishes!" (线段树求动态最大连续和)
- UVALive 3938 "Ray, Pass me the dishes!"
- UVALive3938 "Ray, Pass me the dishes!" 线段树动态区间最大和
- UVALive - 3938:"Ray, Pass me the dishes!"
- UVALive3938 "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!"
- LA-3938-"Ray, Pass me the dishes!" 解题报告
- LA 3938 - "Ray, Pass me the dishes!"(线段树)
- uvalive3938 “Ray, Pass me the dishes!”
- UVALive - 3938 "Ray, Pass me the dishes!" (线段树)
- uvalive 3938 Ray, Pass me the dishes!(线段树)
- UVa 3938 "Ray, Pass me the dishes!"
- UVALive - 3938 "Ray, Pass me the dishes!" 线段树单点更新