每个结点维护3个值,最大连续和max_sub,最大前缀和max_prefix与最大后缀和max_suffix.
思想:最有解要么在左边,要么在右边,要么跨越中点。
维护max_sub的同时维护max_prefix,max_suffix即可。
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const ll INF = -(1LL<<60);
const int MAXN = 500007;
struct node {
int l, r;
ll n;
bool operator < (const node & no) const {
return nno.l || n==no.n&&l==no.l&&r>no.r;
}
}maxv[MAXN << 2];
int maxl[MAXN << 2], maxr[MAXN << 2];
ll x[MAXN], sum[MAXN];
void build(int num, int l, int r) {
if(l == r) {
maxv[num] = node{l, r, x[l]};
maxl[num] = maxr[num] = l;
return ;
}
int m = (l + r) >> 1;
build(num<<1, l, m);
build(num<<1|1, m+1, r);
maxv[num] = node{l, r, INF};
maxv[num] = max(maxv[num], maxv[num<<1]);
maxv[num] = max(maxv[num], maxv[num<<1|1]);
maxv[num] = max(maxv[num], node{maxr[num<<1], maxl[num<<1|1], sum[maxl[num<<1|1]] - sum[maxr[num<<1] - 1]});
maxl[num] = maxl[num<<1];
if(sum[maxl[num]] - sum[l - 1] < sum[maxl[num<<1|1]] - sum[l-1]) maxl[num] = maxl[num<<1|1];
maxr[num] = maxr[num<<1|1];
if(sum[r] - sum[maxr[num] - 1] <= sum[r] - sum[maxr[num<<1] - 1]) maxr[num] = maxr[num<<1];
}
node getans(int num, int l, int r, int a, int b, int &tmaxl, int &tmaxr) {
if(a <= l && b >= r) {
tmaxl = maxl[num];
tmaxr = maxr[num];
return maxv[num];
}
int m = (l+r)>>1;
node ans = node{l, r, INF};
int lmaxr, lmaxl, rmaxl, rmaxr;
tmaxl = tmaxr = -1;
if(a <= m && b > m) {
ans = max(ans, getans(num<<1, l, m, a, b, lmaxl, lmaxr));
ans = max(ans, getans(num<<1|1, m+1, r, a, b, rmaxl, rmaxr));
if(rmaxl != -1 && lmaxr != -1)
ans = max(ans, node{lmaxr, rmaxl, sum[rmaxl] - sum[lmaxr-1]});
if(a <= l) {
tmaxl = lmaxl;
if(sum[lmaxl] - sum[l-1] < sum[rmaxl] - sum[l-1]) tmaxl = rmaxl;
}
if(b >= r) {
tmaxr = rmaxr;
if(sum[r] - sum[rmaxr-1] <= sum[r] - sum[lmaxr-1]) tmaxr = lmaxr;
}
}
else if(a <= m) {
ans = max(ans, getans(num<<1, l, m, a, b, lmaxl, lmaxr));
if(a <= l) tmaxl = lmaxl;
}
else if(b > m) {
ans = max(ans,getans(num<<1|1, m+1, r, a, b, rmaxl, rmaxr));
if(b >= r) tmaxr = rmaxr;
}
return ans;
}
int main() {
int n, m, id = 0;
while(~scanf("%d%d", &n, &m)) {
memset(sum, 0, sizeof(sum));
int i;
for(i = 1; i <= n; i++) {
scanf("%lld", x + i);
sum[i] = sum[i - 1] + x[i];
}
build(1,1,n);
printf("Case %d:\n", ++id);
while(m --) {
int l, r, a, b;
scanf("%d%d", &a, &b);
node ans = getans(1, 1, n, a, b, l, r);
printf("%d %d\n", ans.l, ans.r);
}
}
return 0;
}