• [LA_3938]最大连续动态和


     

    Sample Input

    3 1

    1 2 3

    1 1

    Sample Output

    Case 1:

    1 1

    线段树

    L,R表示该区间的左右端点,sum表示该区间值的总和

    l,r表示该区间连续的最大和的左右端点,maxall表示该区间的连续最大和

    maxqj表示该区间的前缀连续最大和(即val[L]必取),qj表示该区间的前缀连续最大和右端点

    maxhj表示该区间的后缀连续最大和(即val[R]必取),hj表示该区间的前缀连续最大和左端点

    更新maxall:分3类讨论

    1.连续最大和在左子树   或   几种情况中连续最大和相等且这种情况的连续最大和的左端点较小或相等

       取左子树的连续最大和及端点

    2.连续最大和在左右两子树   或   几种情况中连续最大和相等且这种情况的连续最大和的左端点较小

       取左子树的后缀连续最大和加右子树的前缀连续最大和

    3.连续最大和在右子树

       取有子树的连续最大和及端点

    更新maxqj:分两类讨论

    1.前缀连续最大和在左右两子树

       取左子树的区间值的总和加右子树的前缀连续最大和及端点

    2.前缀连续最大和在左子树    或     几种情况中前缀连续最大和相等

       取左子树的前缀连续最大和及端点

    更新maxhj:分两类讨论

    1.后缀连续最大和在左右两子树    或     几种情况中后缀连续最大和相等

     取右子树的区间值的总和加左子树的后缀连续最大和及端点

    2.后缀连续最大和在右子树 

        取右子树的后缀连续最大和及端点

    更新sum:把左右两子树的sum加起来

     对于[a,b],我们用分治的思想,分三种情况讨论:

    1.[a,b]在左子树,对左子树递归调用

    2.[a,b]在右子树,对右子树递归调用

    3.[a,b]在左右子树,对[a,mid],[mid+1,b]分别递归调用

       t1(结构体)表示左子树返回的东西,t2表示右子树返回的东西,t表示该子树返回的东西

      很明显,对于t的更新,和上面对tree的更新一模一样

      如果当前区间与线段树中某区间重合,直接返回线段树中该区间存的内容即可

      记得long long

      

    #include<iostream>
    #include<cstdio>
    using namespace std;
    typedef long long ll;
    int val[500001],n,m;
    struct xxx{
        int L,R;
        int l,r,qj,hj;
        ll sum,maxqj,maxhj,maxall;
    }tree[2000001];
    inline int read(){
        int x;bool f;char c;
        for (f=0; (c=getchar())<'0'||c>'9'; f=c=='-');
        for (x=c-'0'; (c=getchar())>='0'&&c<='9'; x=(x<<3)+(x<<1)+c-'0');
        return f?-x:x;
    }
    void pushup(int x)
    {
        ll x1=tree[x<<1].maxall,x2=tree[x<<1].maxhj+tree[x<<1|1].maxqj,x3=tree[x<<1|1].maxall;
        if(x1>=x3&&(x1>x2||x1==x2&&tree[x<<1].l<=tree[x<<1].hj))
            tree[x].maxall=x1,tree[x].l=tree[x<<1].l,tree[x].r=tree[x<<1].r;
        else if(x2>=x3)
            tree[x].maxall=x2,tree[x].l=tree[x<<1].hj,tree[x].r=tree[x<<1|1].qj;
        else 
            tree[x].maxall=x3,tree[x].l=tree[x<<1|1].l,tree[x].r=tree[x<<1|1].r;
        if(tree[x<<1].sum+tree[x<<1|1].maxqj>tree[x<<1].maxqj)
            tree[x].maxqj=tree[x<<1].sum+tree[x<<1|1].maxqj,tree[x].qj=tree[x<<1|1].qj;
        else
            tree[x].maxqj=tree[x<<1].maxqj,tree[x].qj=tree[x<<1].qj;
        if(tree[x<<1|1].sum+tree[x<<1].maxhj>=tree[x<<1|1].maxhj)
            tree[x].maxhj=tree[x<<1|1].sum+tree[x<<1].maxhj,tree[x].hj=tree[x<<1].hj;
        else
            tree[x].maxhj=tree[x<<1|1].maxhj,tree[x].hj=tree[x<<1|1].hj;
        tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
    }
    void build(int x,int l,int r)
    {
        if(l==r)
        {
            tree[x].sum=tree[x].maxqj=tree[x].maxhj=tree[x].maxall=(ll)val[l];  
              tree[x].l=tree[x].r=tree[x].qj=tree[x].hj=tree[x].L=tree[x].R=l;return;  
        }
        tree[x].L=l;tree[x].R=r;
        int mid=(l+r)>>1;
        build(x<<1,l,mid);build(x<<1|1,mid+1,r);pushup(x);
        //cout<<l<<" "<<r<<" "<<tree[x].maxall<<" "<<tree[x].l<<" "<<tree[x].r<<tree[x].hj<<endl;
    }
    xxx query(int x,int l,int r)
    {
        if(l==tree[x].L&&r==tree[x].R)return tree[x];
        int mid=(tree[x].L+tree[x].R)/2;
        if(r<=mid)return query(x<<1,l,r);
        else if(l>mid)return query(x<<1|1,l,r);
        else
        {
            xxx t1=query(x<<1,l,mid),t2=query(x<<1|1,mid+1,r),t;
                ll x1=t1.maxall,x2=t1.maxhj+t2.maxqj,x3=t2.maxall;
            if(x1>=x3&&(x1>x2||x1==x2&&t1.l<=t1.hj))
                t.maxall=x1,t.l=t1.l,t.r=t1.r;
            else if(x2>=x3)
                t.maxall=x2,t.l=t1.hj,t.r=t2.qj;
            else 
                t.maxall=x3,t.l=t2.l,t.r=t2.r;
            if(t1.sum+t2.maxqj>t1.maxqj)
                t.maxqj=t1.sum+t2.maxqj,t.qj=t2.qj;
            else
                t.maxqj=t1.maxqj,t.qj=t1.qj;
            if(t2.sum+t1.maxhj>=t2.maxhj)
                t.maxhj=t2.sum+t1.maxhj,t.hj=t1.hj;
            else
                t.maxhj=t2.maxhj,t.hj=t2.hj;
            return t;
        }
        
    }
    int main()
    {
        int T=0;
        while(~scanf("%d%d",&n,&m))
        {
            T++;
            for(int i=1;i<=n;i++)val[i]=read();
            build(1,1,n);
            printf("Case %d:
    ",T);
            for(int i=1;i<=m;i++)
            {
                int a=read(),b=read();
                xxx x=query(1,a,b);
                printf("%d %d
    ",x.l,x.r);
            }
        }
        return 0;
    }
  • 相关阅读:
    启动Mysql后找不到服务或出现找不到指定文件
    WEB-MVC模式图示
    Java中Map集合的遍历方式
    sun.misc.BASE64Encoder找不到jar包的解决方法
    Tomcat常用的网站发布方式
    Sql Server查询行号
    Mysql下载安装问题
    【数学】环逆序
    【搜索】【the first editoral】OpenJudge 我是最快的马
    The First Blog
  • 原文地址:https://www.cnblogs.com/lher/p/7134205.html
Copyright © 2020-2023  润新知