Ray, Pass me the dishes!

题目:https://cn.vjudge.net/problem/UVALive-3938

将数列二分存储在线段树

并记录每段前缀最大值qian,后缀最大值hou,总合sum,最大中间和w

与各自坐标;

建记录如上的线段树(更新规则见代码)

后得到范围解题便可!

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct node{
long long qian,hou,w,sum;
int l,r,p,s;
}e[2000010];
long long c[500005];
long long read()
{
long long x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void build(int a,int b,int o)
{
if(a==b)
{
e[o].sum=e[o].w=e[o].qian=e[o].hou=c[a];
e[o].l=e[o].r=e[o].p=e[o].s=a;
return ;
}
int mid=(a+b)/2;
build(a,mid,2*o);
build(mid+1,b,2*o+1);
e[o].sum=e[2*o].sum+e[2*o+1].sum;
long long a1=e[2*o].w,a2=e[2*o+1].w,s1=e[2*o].hou+e[2*o+1].qian;
if(a1>=a2&&a1>=s1){e[o].w=a1;e[o].l=e[2*o].l;e[o].r=e[2*o].r;}
else if(s1>=a2){e[o].w=s1;e[o].l=e[2*o].s;e[o].r=e[2*o+1].p;}
else {e[o].w=a2;e[o].l=e[2*o+1].l;e[o].r=e[2*o+1].r;}
if(e[2*o].qian>=e[2*o].sum+e[2*o+1].qian)
{e[o].qian=e[2*o].qian;e[o].p=e[2*o].p; }
else
{ e[o].qian=e[2*o].sum+e[2*o+1].qian;e[o].p=e[2*o+1].p; }
if(e[2*o+1].hou>e[2*o].hou+e[2*o+1].sum)
{ e[o].hou=e[2*o+1].hou;e[o].s=e[2*o+1].s;}
else
{ e[o].hou=e[2*o+1].sum+e[2*o].hou;e[o].s=e[2*o].s;}
}
node jie(int c,int l,int r,int L,int R)
{
if(L==l&&R==r)return e[c];
int mid=L+(R-L)/2;
if(r<=mid)return jie(2*c,l,r,L,mid);
else if(l>mid)return jie(2*c+1,l,r,mid+1,R);
else
{
node ri,le,da;
ri=jie(2*c,l,mid,L,mid);
le=jie(2*c+1,mid+1,r,mid+1,R);
da.sum=le.sum+ri.sum;
if(ri.w>=le.w&&ri.w>=ri.hou+le.qian){da.w=ri.w;da.l=ri.l;da.r=ri.r;}
else if(ri.hou+le.qian>=le.w){da.w=ri.hou+le.qian;da.l=ri.s;da.r=le.p;}
else {da.w=le.w;da.l=le.l;da.r=le.r;}
if(ri.qian>=ri.sum+le.qian)
{da.qian=ri.qian;da.p=ri.p;}
else
{da.qian=ri.sum+le.qian;da.p=le.p;}
if(le.hou>ri.hou+le.sum)
{ da.hou=le.hou;da.s=le.s;}
else
{da.hou=le.sum+ri.hou;da.s=ri.s;}
return da;
}
}
int main()
{
int n,m,t=0;;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(int i=1;i<=n;i++)
c[i]=read();
build(1,n,1);
node ans;
t++;
cout<<"Case "<<t<<":"<<endl;
for(int i=0;i<m;i++)
{
int l=read(),r=read();
ans=jie(1,l,r,1,n);
cout<<ans.l<<" "<<ans.r<<endl;
}
}
return 0;
}

posted @ 2017-07-10 15:21  0degreeofsail  阅读(152)  评论(0编辑  收藏  举报