思路: 记录每一个节点最大前缀和 和 最大后缀和 和最大子序列的 <x,y> 主要是注意在push_up的时候 注意区间的合并。
代码:
#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1)
using namespace std;
typedef long long ll;
typedef pair<int ,int > pii;
const int N =500000+5;
struct node
{
int l,r;
pii maxsub;
int pre;
int post;
}tree[N<<2];
ll sum[N];
ll getsum(int l,int r)
{
return sum[r]-sum[l-1];
}
pii better(pii a,pii b)
{
ll sum1=getsum(a.first,a.second); ll sum2=getsum(b.first,b.second);
if(sum1!=sum2){
return sum1>sum2?a:b;
}
return a<b?a:b; // 返回下标小的
}
void build(int i,int l,int r)
{
tree[i].l=l; tree[i].r=r;
if(l==r){
tree[i].maxsub=pii(l,l);
tree[i].post=tree[i].pre=l;
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
// 计算前缀和
ll sum1=getsum(l,tree[lson].pre);
ll sum2=getsum(l,tree[rson].pre);
if(sum1==sum2){
tree[i].pre=min(tree[lson].pre,tree[rson].pre);
}
else{
tree[i].pre=sum1>sum2?tree[lson].pre:tree[rson].pre;
}
// 计算后缀和
sum1=getsum(tree[lson].post,r);
sum2=getsum(tree[rson].post,r);
if(sum1==sum2){
tree[i].post=min(tree[lson].post,tree[rson].post);
}
else tree[i].post=sum1>sum2?tree[lson].post:tree[rson].post;
tree[i].maxsub=better(tree[lson].maxsub,tree[rson].maxsub);
tree[i].maxsub=better(tree[i].maxsub,pii(tree[lson].post,tree[rson].pre));
return ;
}
pii query_post(int i,int l,int r)
{
if(tree[i].post>=l) return pii(tree[i].post,r);
int mid=(tree[i].l+tree[i].r)>>1;
if(l>mid) return query_post(rson,l,r);
pii x1=query_post(lson,l,mid);
x1.second=r;
return better(x1,pii(tree[rson].post,r));
}
pii query_pre(int i,int l,int r)
{
if(tree[i].pre<=r) return pii(l,tree[i].pre);
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid) return query_pre(lson,l,r);
pii x1=query_pre(rson,mid+1,r);
x1.first=l;
return better(x1,pii(l,tree[lson].pre));
}
pii query(int i,int l,int r)
{
if(l==tree[i].l&&r==tree[i].r){
return tree[i].maxsub;
}
int mid=(tree[i].l+tree[i].r)>>1;
if(r<=mid) return query(lson,l,r);
else if(l>mid) return query(rson,l,r);
pii x1=query_post(lson,l,mid); // 左子树的后缀
pii x2=query_pre(rson,mid+1,r); // 右子树的前缀
//cout<<"lala"<<x1.first<<" "<<x2.second<<endl;
pii x3=better(query(lson,l,mid),query(rson,mid+1,r));
return better( x3, pii(x1.first,x2.second) );
}
int n,m;
int main()
{
int kk=0;
while(cin>>n>>m)
{
ll x;
memset(sum,0,sizeof(sum));
for(int i=1;i<=n;i++)
{
scanf("%lld",&x);
sum[i]=sum[i-1]+x;
}
build(1,1,n);
/*
for(int i=1;i<=10;i++)
{
cout<<tree[i].l<<" "<<tree[i].r<<" "<<tree[i].maxsub.first<<" "<<tree[i].maxsub.second<<" "<<tree[i].pre<<" "<<tree[i].post<<endl;
}
*/
int l,r;
printf("Case %d:\n",++kk);
while(m--)
{
scanf("%d %d",&l,&r);
pii ans=query(1,l,r);
printf("%d %d\n",ans.first,ans.second);
}
}
return 0;
}
/*
4 3
4 5 -7 6
2 4
3 4
1 4
*/