思路:线段树。
代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <deque>
#include <set>
#include <cstring>
#include <map>
using namespace std;
#define ll long long
#define maxn 500000
struct Pair {
int x,y;
Pair() {}
Pair(int x_,int y_) {
x=x_,y=y_;
}
bool operator <(const Pair& other) const {
return x<other.x||(x==other.x&&y<other.y)?true:false;
}
};
int n,m;
ll a[maxn+5]; //前缀和
Pair maxsub[2*maxn+5]; //最大连续和
int maxpre[2*maxn+5],maxsuf[2*maxn+5]; //最大前缀、后缀
int X,Y;
Pair cmp(Pair x1,Pair x2) { //比较x1,x2那段更优
ll y1=a[x1.y]-a[x1.x-1],y2=a[x2.y]-a[x2.x-1];
if(y1>y2) return x1; //值的大小
if(y1==y2&&x1<x2) return x1; //坐标的大小
return x2;
}
void buildtree(int o,int L,int R) {
if(L==R) { //叶子节点
maxsub[o]=Pair(L,R);
maxpre[o]=maxsuf[o]=L;
return ;
}
int lson=o*2,rson=o*2+1;
int mid=(L+R)/2;
buildtree(lson,L,mid);
buildtree(rson,mid+1,R);
if(a[maxpre[lson]]>=a[maxpre[rson]]) maxpre[o]=maxpre[lson];
else maxpre[o]=maxpre[rson];
if(a[maxsuf[lson]-1]<=a[maxsuf[rson]-1]) maxsuf[o]=maxsuf[lson]; //即a[R]-a[maxsuf[lson]-1]>=a[R]-a[maxsuf[rson]-1]
else maxsuf[o]=maxsuf[rson];
maxsub[o]=cmp(Pair(maxsuf[lson],maxpre[rson]),cmp(maxsub[lson],maxsub[rson]));
}
Pair qpre(int o,int L,int R) { //前缀最大值
if(maxpre[o]<=Y) return Pair(L,maxpre[o]); //最大前缀被所求区间涵盖
int mid=(L+R)/2;
int lson=2*o,rson=2*o+1;
if(Y<=mid) return qpre(lson,L,mid); //只在左边
Pair x=qpre(rson,mid+1,R);
x.x=L;
return cmp(x,Pair(L,maxpre[lson]));
}
Pair qsuf(int o,int L,int R) { //后缀最大值
if(maxsuf[o]>=X) return Pair(maxsuf[o],R);
int mid=(L+R)/2;
int lson=2*o,rson=2*o+1;
if(X>mid) return qsuf(rson,mid+1,R);
Pair x=qsuf(lson,L,mid);
x.y=R;
return cmp(x,Pair(maxsuf[rson],R));
}
Pair query(int o,int L,int R) {
if(X<=L&&Y>=R) return maxsub[o];
int lson=o*2,rson=o*2+1;
int mid=(L+R)/2;
if(Y<=mid) return query(lson,L,mid); //全左
if(X>mid) return query(rson,mid+1,R); //全右
Pair b=Pair(qsuf(lson,L,mid).x,qpre(rson,mid+1,R).y); //左右各一半
Pair c=query(lson,L,mid),d=query(rson,mid+1,R); //有时,完全在一边的一段比左右各一半的一段更大
return cmp(b,cmp(c,d));
}
int main() {
int T=0;
while(~scanf("%d%d",&n,&m)) {
for(int i=1; i<=n; i++) {
int x;
scanf("%d",&x);
a[i]=a[i-1]+x;
}
buildtree(1,1,n);
printf("Case %d:\n",++T);
for(int i=1; i<=m; i++) {
scanf("%d%d",&X,&Y);
if(X>Y) swap(X,Y);
Pair ans=query(1,1,n);
printf("%d %d\n",ans.x,ans.y);
}
}
return 0;
}