zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    各种版本控制器的作用
    mybatis的一些特殊符号标识(大于,小于,等于,不等于)
    struts2的作用是什么
    js中给数组添加元素的方法有哪些
    springmvc中拦截器配置格式
    js中require()的用法----JS如何连接数据库执行sql语句或者建立数据库连接池
    hover()函数的用法
    error和exception的不同与相同
    cookie和session的区别有哪些
    数据库连接池的工作机制是什么
  • 原文地址:https://www.cnblogs.com/lher/p/7134205.html
Copyright © 2011-2022 走看看