"Ray, Pass me the dishes!"
题意:给出一个长度为n的序列D,对于m个询问(a,b)找到两个下标x,y使得a<=x<=y<=b,Da+...+Db尽量大,输出x可能小,y也可能小的结果。
思路:构造一颗线段树,每个结点维护3个值,最大连续和max_sub,最大前缀和max_perfix,最大后缀和max_suffix,最后只有3种情况。
1连续最大和都在左子树区间内
2连续最大和都在右子树区间内
3连续最大和在整个区间内(左子树的最大后缀+右子树的最大前缀)
具体实现看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=500005;
ll sum[N];
int ql,qr;
struct node{
int max_perfix;
int max_suffix;
pair<int,int>max_sub;
}node[4*N];
ll cal_sum(int l,int r){
return sum[r]-sum[l-1];
}
pair<int,int>cmp(pair<int,int>a,pair<int,int>b){
if(cal_sum(a.first,a.second)>cal_sum(b.first,b.second))
return a;
else if(cal_sum(a.first,a.second)<cal_sum(b.first,b.second))
return b;
else if(a<b)
return a;
else return b;
}
void build(int o,int l,int r){
if(l==r){
node[o].max_perfix=node[o].max_suffix=l;
node[o].max_sub=make_pair(l,l);
return;
}
int mid=(l+r)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
ll x1,x2;
x1=cal_sum(l,node[o*2].max_perfix);
x2=cal_sum(l,node[o*2+1].max_perfix);
if(x1>=x2)
node[o].max_perfix=node[o*2].max_perfix;
else node[o].max_perfix=node[o*2+1].max_perfix;
x1=cal_sum(node[o*2].max_suffix,r);
x2=cal_sum(node[o*2+1].max_suffix,r);
if(x1>=x2)
node[o].max_suffix=node[o*2].max_suffix;
else node[o].max_suffix=node[o*2+1].max_suffix;
node[o].max_sub=cmp(node[o*2].max_sub,node[o*2+1].max_sub);
node[o].max_sub=cmp(node[o].max_sub,make_pair(node[o*2].max_suffix,node[o*2+1].max_perfix));
}
pair<int,int>query_perfix(int o,int l,int r){
if(qr>=node[o].max_perfix)
return make_pair(l,node[o].max_perfix);
int mid=(l+r)/2;
if(qr<=mid)
return query_perfix(o*2,l,mid);
pair<int,int>x;
x=query_perfix(o*2+1,mid+1,r);
x.first=l;
return cmp(make_pair(l,node[o*2].max_perfix),x);
}
pair<int,int>query_suffix(int o,int l,int r){
if(ql<=node[o].max_suffix)
return make_pair(node[o].max_suffix,r);
int mid=(l+r)/2;
if(ql>mid)
return query_suffix(o*2+1,mid+1,r);
pair<int,int>x;
x=query_suffix(o*2,l,mid);
x.second=r;
return cmp(make_pair(node[o*2+1].max_suffix,r),x);
}
pair<int,int>query(int o,int l,int r){
if(ql<=l&&qr>=r)
return node[o].max_sub;
int mid=(l+r)/2;
if(qr<=mid)
return query(o*2,l,mid);
if(ql>mid)
return query(o*2+1,mid+1,r);
pair<int,int>x1,x2,x3;
x1=query_suffix(o*2,l,mid);
x2=query_perfix(o*2+1,mid+1,r);
x3=cmp(query(o*2,l,mid),query(o*2+1,mid+1,r));
return cmp(make_pair(x1.first,x2.second),x3);
}
int main(){
int n,m;
int cnt=1;
while(~scanf("%d%d",&n,&m)){
int x;
sum[0]=0;
for(int i=1;i<=n;i++){
scanf("%d",&x);
sum[i]=sum[i-1]+x;
}
build(1,1,n);
printf("Case %d:\n",cnt++);
for(int i=0;i<m;i++){
scanf("%d%d",&ql,&qr);
pair<int,int>ans=query(1,1,n);
printf("%d %d\n",ans.first,ans.second);
}
}
return 0;
}