題目鏈接:
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=1939
來自:劉汝佳大白書P201.
解題思路:
機關一棵線段樹,此中每個結點保護三個值,記錄最大前綴和,最大後綴和最大連氣兒和。
最大連氣兒和要麼完全在左段,要麼完全在右段,要麼在跨越中線。就是會是左段的最大後綴和+右段的最大前綴和。。。。
#include <iostream>
#include <cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#include<math.h>
#include<queue>
#include<utility>
#define INF 2000000000
#define maxn 500005LL
#define max(a,b) (a)>(b)?(a):(b)
#define min(a,b) (a)<(b)?(a):(b)
#define ls(o) o<<1
#define rs(o) o<<1|1
using namespace std;
typedef pair<int,int> Interval;
typedef long long ll;
ll prefix_sum[510005];
ll sum(int l,int r)
{
return prefix_sum[r] - prefix_sum[l-1];
}
ll sum(Interval p)
{
return sum(p.first,p.second);
}
Interval better(Interval a,Interval b)
{
ll t1=sum(a),t2=sum(b);
if(t1==t2)return a<b?a:b;
else{
return t1>t2?a:b;
}
}
struct line_tree{
int prefix;
int suffix;
int l, r;
Interval sub;
}tree[maxn<<2];
void build(int l,int r,int o)
{
tree[o].l=l,tree[o].r=r;
if(l==r){
tree[o].prefix=tree[o].suffix=l;
tree[o].sub = make_pair(l,l);
return ;
}
int mid = (l+r)>>1;
build(l,mid,ls(o));
build(mid+1,r,rs(o));
ll t1 = sum(l,tree[ls(o)].prefix);
ll t2 = sum(l,tree[rs(o)].prefix);
if(t1==t2)tree[o].prefix = min(tree[ls(o)].prefix,tree[rs(o)].prefix);
else tree[o].prefix = t1>t2?tree[ls(o)].prefix:tree[rs(o)].prefix;
t1 = sum(tree[ls(o)].suffix,r);
t2 = sum(tree[rs(o)].suffix,r);
if(t1==t2)tree[o].suffix = min(tree[ls(o)].suffix,tree[rs(o)].suffix);
else tree[o].suffix = t1>t2?tree[ls(o)].suffix:tree[rs(o)].suffix;
tree[o].sub = better(tree[ls(o)].sub,tree[rs(o)].sub);
tree[o].sub = better(tree[o].sub,make_pair(tree[ls(o)].suffix,tree[rs(o)].prefix));
}
Interval query_prefix(int l,int r,int o)
{
if(tree[o].prefix<=r)return make_pair(l,tree[o].prefix);
if(r<=tree[ls(o)].r)return query_prefix(l,r,ls(o));
Interval t = query_prefix(l,r,rs(o));
t.first = l;
return better(t,make_pair(l,tree[ls(o)].prefix));
}
Interval query_suffix(int l,int r,int o)
{
if(tree[o].suffix>=l)return make_pair(tree[o].suffix,r);
if(l>=tree[rs(o)].l)return query_suffix(l,r,rs(o));
Interval t = query_suffix(l,r,ls(o));
t.second = r;
return better(t,make_pair(tree[rs(o)].suffix,r));
}
Interval query(int l,int r,int o)
{
if(l<=tree[o].l&&tree[o].r<=r)return tree[o].sub;
if(r<=tree[ls(o)].r)return query(l,r,ls(o));
if(l>=tree[rs(o)].l)return query(l,r,rs(o));
Interval t1 = query_suffix(l,r,ls(o));
Interval t2 = query_prefix(l,r,rs(o));
Interval t3 = better(query(l,r,ls(o)),query(l,r,rs(o)));
return better(t3,make_pair(t1.first,t2.second));
}
int main()
{
int n,m,t=1;
while(scanf("%d%d",&n,&m)==2){
printf("Case %d:\n",t++);
prefix_sum[0] = 0;
for(int i=1;i<=n;i++){
scanf("%lld",&prefix_sum[i]);
prefix_sum[i]+=prefix_sum[i-1];
}
build(1,n,1);
int a,b;
for(int i=1;i<=m;i++){
scanf("%d%d",&a,&b);
Interval p = query(a,b,1);
printf("%d %d\n",p.first,p.second);
}
}
}