白书上的线段树例题。
题意 : 给你一个数组,然后有m次询问,每次询问一个区间,返回在这个区间里面最大的连续和的起始和结束位置、
思路 :每个节点记录前缀max_pre和和后缀和max_suf来维护它的最大连续和max_sub。(其实思路白书上讲了,就是代码实现而已)需要注意的是这道题目的max_pre,max_suf,max_sub都是需要用long long 来保存的。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long lld;
const int MAXN = 500005;
const int INF = 100000007;
struct MAX
{
lld Max;
int l,r;
};
struct node
{
MAX sub, pre, suf;
lld sum;
}ans[MAXN<<2];
int n,m;
void init(node &a,int v)
{
MAX e;
e.Max = v;
e.l = -INF; e.r = INF;
a.pre = a.sub = a.suf = e;
a.sum = v;
}
void push_up(node &mid,node &ll,node &rr)
{
mid.sum = ll.sum + rr.sum;
if (ll.pre.Max >= rr.pre.Max + ll.sum)
{
mid.pre = ll.pre;
}
else
{
mid.pre.Max = rr.pre.Max + ll.sum;
mid.pre.l = ll.pre.l;
mid.pre.r = rr.pre.r;
}
if (rr.suf.Max > rr.sum + ll.suf.Max)
{
mid.suf = rr.suf;
}
else
{
mid.suf.Max = rr.sum + ll.suf.Max;
mid.suf.l = ll.suf.l;
mid.suf.r = rr.suf.r;
}
lld temp = ll.suf.Max + rr.pre.Max;
lld t1 = ll.sub.Max, t2 = rr.sub.Max;
if (t1 >= temp && t1 >= t2)
{
mid.sub = ll.sub;
}
else if (temp >= t1 && temp >= t2)
{
mid.sub.Max = temp;
mid.sub.l = ll.suf.l;
mid.sub.r = rr.pre.r;
}
else
{
mid.sub = rr.sub;
}
}
void update(int rt,int L,int R,int p,int v)
{
if (L == R)
{
ans[rt].sub.Max = ans[rt].pre.Max = ans[rt].suf.Max = v;
ans[rt].sum = v;
ans[rt].sub.l = ans[rt].sub.r = p;
ans[rt].pre.l = ans[rt].pre.r = p;
ans[rt].suf.l = ans[rt].suf.r = p;
}
else
{
int M = (L + R) >> 1;
if (p <= M)update(rt<<1,L,M,p,v);
else update(rt<<1|1,M+1,R,p,v);
if (ans[rt<<1].sum != -INF)
{
if (ans[rt<<1|1].sum != -INF)
push_up(ans[rt],ans[rt<<1],ans[rt<<1|1]);
else ans[rt] = ans[rt<<1];
}
else ans[rt] = ans[rt<<1|1];
}
}
node query(int rt,int L,int R,int l,int r)
{
int M = (L + R) >> 1;
node tl,tr,res;
init(tl,-INF); init(tr,-INF);
if (L >= l && R <= r)return ans[rt];
if (M >= l)
{
tl = query(rt<<1,L,M,l,r);
}
if (r > M)
{
tr = query(rt<<1|1,M+1,R,l,r);
}
if (tl.sum != -INF)
{
if (tr.sum != -INF)
{
push_up(res,tl,tr);
return res;
}
else return tl;
}
else return tr;
}
int main()
{
int cas = 1 , i;
while (scanf("%d%d",&n,&m) == 2)
{
for (i = 1;i <= 4*n;i++)init(ans[i],-INF);
for (i = 1;i <= n;i++)
{
int a;
scanf("%d",&a);
update(1,1,n,i,a);
}
printf("Case %d:\n",cas++);
while (m--)
{
int ql,qr;
scanf("%d%d",&ql,&qr);
node res = query(1,1,n,ql,qr);
printf("%d %d\n",res.sub.l,res.sub.r);
}
}
return 0;
}