LA 3938 - "Ray, Pass me the dishes!"(线段树)

来源:互联网 发布:预测股票涨跌软件 编辑:程序博客网 时间:2024/05/22 14:23

动态最大连续和。

思路:完全参照刘汝佳厚书的思路。

几天前,就从书上得到一个思路,却不知怎么实现,于是乎,几天来一直广搜结题报告,结合人家现成的代码,今天写成了代码,又调了半下午的bug,终于ac了。

构造一课线段树,其中每个节点维护3个信息,最大连续和(x,y),最大前缀和(pre),最大后缀和(suf),虽然都叫做什么什么和,存的却都是位置标记,

1、建树

2、若干次查询

这道题目没有加入树节点的修改,算是数据结构中的基础题了。

思路来自于静态最大连续和的求解,(最大连续和或在[1...m],或在[m+1......n],或在[x...m......y])

代码如下:

#include <cstdio>#include <algorithm>using namespace std;#define M 500005struct Node{    int x, y, pre, suf, subx, suby;};int n, m;long long a[M], sum[M];Node tree[2*M+10];void creat(int x, int y, int o){    if(x==y)    {        tree[o].x = x;        tree[o].y = x;        tree[o].pre = x;        tree[o].suf = x;        tree[o].subx = x;        tree[o].suby = x;        return;    }    int m = (x+y)/2;    creat(x, m, 2*o);    creat(m+1, y, 2*o+1);    tree[o].x = x;    tree[o].y = y;    tree[o].pre = sum[tree[2*o].pre]-sum[x-1] >= sum[tree[2*o+1].pre]-sum[x-1] ? tree[2*o].pre : tree[2*o+1].pre;    tree[o].suf = sum[y]-sum[tree[2*o].suf-1] >= sum[y]-sum[tree[2*o+1].suf-1] ? tree[2*o].suf : tree[2*o+1].suf;    if(sum[tree[2*o].suby]-sum[tree[2*o].subx-1]>=sum[tree[2*o+1].suby]-sum[tree[2*o+1].subx-1])        { tree[o].suby = tree[2*o].suby; tree[o].subx = tree[2*o].subx; }    else        { tree[o].suby = tree[2*o+1].suby; tree[o].subx = tree[2*o+1].subx; }    if(sum[tree[2*o+1].pre]-sum[tree[2*o].suf-1] > sum[tree[o].suby]-sum[tree[o].subx-1])        { tree[o].subx = tree[2*o].suf; tree[o].suby = tree[2*o+1].pre; }    else if(sum[tree[2*o+1].pre]-sum[tree[2*o].suf-1] == sum[tree[o].suby]-sum[tree[o].subx-1])    {        if(tree[o].subx > tree[2*o].suf||(tree[o].subx == tree[2*o].suf && tree[o].suby > tree[2*o+1].pre))            { tree[o].subx = tree[2*o].suf; tree[o].suby = tree[2*o+1].pre; }    }}void buildtree(){    creat(1,n,1);}void query(int o, int ql, int qr, int &ansx, int &ansy, int &pre, int &suf){    int x = tree[o].x,  y = tree[o].y;    if(ql<=x&&qr>=y)    {        ansx = tree[o].subx;        ansy = tree[o].suby;        pre = tree[o].pre;        suf = tree[o].suf;        return ;    }    int mid = (x+y)/2;    if(qr<=mid) query(2*o,ql,qr,ansx,ansy,pre,suf);    else if(ql>mid) query(2*o+1,ql,qr,ansx,ansy,pre,suf);    else    {        int x1, x2, y1, y2,p1,p2,s1,s2;        query(2*o,ql,mid,x1,y1,p1,s1);        query(2*o+1,mid+1,qr,x2,y2,p2,s2);        pre = sum[p1]-sum[ql-1] >= sum[p2]-sum[ql-1] ? p1 : p2 ;        suf = sum[qr]-sum[s1-1] >= sum[qr]-sum[s2-1] ? s1 : s2 ;        if(sum[y1]-sum[x1-1] >= sum[y2]-sum[x2-1])        {            ansx = x1;            ansy = y1;        }        else        {            ansx = x2;            ansy = y2;        }        long long L = sum[m]-sum[s1-1];        long long R = sum[p2]-sum[m];        if(L+R > sum[ansy]-sum[ansx-1] || (L+R == sum[ansy]-sum[ansx-1] && ansx > s1) || (L+R == sum[ansy]-sum[ansx-1] && ansx == s1 && ansy > p2))        {            ansx = s1;            ansy = p2;        }    }}int main (){    int k = 0;    while(~scanf("%d %d",&n, &m))    {        for(int i = 1; i <= n; ++i)        {            scanf("%lld",&a[i]);            sum[i] = sum[i-1]+a[i];        }        buildtree();        int ql, qr, ansx, ansy,pre,suf;        printf("Case %d:\n",++k);//不要把case放错位置哦        while(m--)        {            scanf("%d %d",&ql, &qr);            query(1, ql, qr, ansx, ansy,pre,suf);            printf("%d %d\n", ansx, ansy);        }    }    return 0;}


原创粉丝点击