最大连续动态和(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:\n",T);
        for(int i=1;i<=m;i++)
        {
            int a=read(),b=read();
            xxx x=query(1,a,b);
            printf("%d %d\n",x.l,x.r);
        }
    }
    return 0;
}
时间: 2025-01-31 07:39:48

最大连续动态和(LA_3938)的相关文章

把连续动态bmp转换为avi

把动态bmp24转换为avi BYTE tmp_buf[1024*768*4]; //生成avi void BMPtoAVI(CString szAVIName, CString strBmpDir) { CFileFind finder; strBmpDir += _T("\\*.bmp"); AVIFileInit(); AVISTREAMINFO strhdr; PAVIFILE pfile; PAVISTREAM ps; int nFrames =0; HRESULT hr;

第十章 动态数组

当写下这个题目的时候,笔者心里其实非常犯难.因为从本质上来说,本章想阐述的内容与题目所宣示的概念,其实是不一样的.在编程中,我们常常要处理一段长度未知的数据,而且,运行过程中长度可能会发生变化,现行的C/C++标准没有提供在栈段和数据段内存中的实现,只提供堆中的实现,例如可以象下面代码那样在堆中分配一段内存,以处理一组长度不确定的整数: int *p = ( int* )malloc( n * sizeof( int ) ); 现在我们常常将这段堆内存称为“动态数组”.这正确吗?数组是一个高层概

腾讯技术分享:GIF动图技术详解及手机QQ动态表情压缩技术实践

本文来自腾讯前端开发工程师" wendygogogo"的技术分享,作者自评:"在Web前端摸爬滚打的码农一枚,对技术充满热情的菜鸟,致力为手Q的建设添砖加瓦." 1.GIF格式的历史 GIF ( Graphics Interchange Format )原义是"图像互换格式",是 CompuServe 公司在1987年开发出的图像文件格式,可以说是互联网界的老古董了. GIF 格式可以存储多幅彩色图像,如果将这些图像((https://www.q

Unity3D之碰撞体,刚体

一 概念介绍 刚体 Rigidbody(刚体)组件可使游戏对象在物理系统的控制下来运动,刚体可接受外力与扭矩力用来保证游戏对象像在真实世界中那样进行运动.任何游戏对象只有添加了刚体组件才能受到重力的影响,通过脚本为游戏对象添加的作用力以及通过NVIDIA物理引擎与其他的游戏对象发生互动的运算都需要游戏对象添加了刚体组件. 碰撞体 碰撞体是物理组件的一类,它要与刚体一起添加到游戏对象上才能触发碰撞.如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞,在物理模拟中,没有碰撞体的刚体

浓缩的才是精华:浅析GIF格式图片的存储和压缩

GIF(Graphics Interchange Format)原义是"图像互换格式",是CompuServe公司在1987年开发出的图像文件格式,可以说是互联网界的老古董了. GIF格式可以存储多幅彩色图像,如果将这些图像连续播放出来,就能够组成最简单的动画.所以常被用来存储"动态图片",通常时间短,体积小,内容简单,成像相对清晰,适于在早起的慢速互联网上传播. 本来,随着网络带宽的拓展和视频技术的进步,这种图像已经渐渐失去了市场.可是,近年来流行的表情包文化,让

【Unity】11.2 刚体(Rigidbody)

分类:Unity.C#.VS2015 创建日期:2016-05-02 一.简介 Rigidbody(刚体)组件可使游戏对象在物理系统的控制下来运动,刚体可接受外力与扭矩力,使游戏对象像在真实世界中那样进行运动. 任何游戏对象,只有对其添加了刚体组件,该对象才能受重力的影响. 通过脚本为游戏对象添加的作用力,以及通过NVIDlA物理引擎与其他的游戏对象发生互动的运算,都需要为游戏对象添加刚体组件. 二.如何为对象添加刚体 在Unity 5.x中为某个游戏对象添加刚体组件的办法是:选中要添加刚体的游

堆栈指针 ---delete 使用

对拥有堆中一个有效对象的地址的指针进行删除操作的结果,是将这个堆内存的状态从“使用中” 变为“可用”(此时的可用就是指可以调用内存)释放了,可以再次覆盖此处;; 对指针内存进行删除操作后,指针本身的状态就是未定义的; *******可以是  大多数情况下:  依旧保存所删除的内存地址 我们的delete 仅仅是调用了析构函数,进行对打开对象的调用. 二,我们operator delete进行释放内存;; 因此我们使用的内存,变为仅仅的可用, 此时防止我们的误操作,我们一般将其定义为 NULL ;

《具身认知》听书笔记

具身认知是在反对传统认知科学之偏误的基础上出现的.在传统的认知科学中,人的心智遭以简化为对自然.世界的准确镜像,认知活动在于摒弃.剔除身体的生理参与及经验的嵌入.具身认知真正把人视作“整全的人”,主张认知是大脑.身体与环境交互作用的产物,强调人的身心整全意义上的发展.它强调“具身性”与“情境化”,将对认知的认识从个体加工机制的探讨转向社会实践活动的分析:并认为认知结构具有时间属性,某一时刻的认知状态只是连续动态变化中的一个即时状态,因此主张把实验法和自然法融通起来,在真实.自然的情境中对认知过程

Unity 重要基础知识点

这是两个月前的学习记录,发出来了下,如果有误欢迎大家指出: 脚本生命周期 //每当脚本被加载时调用一次 // 1.   在Awake中做一些初始化操作 void Awake(){ //初始化public成员 } // 2.   在每次激活脚步时调用 void OnEnable(){} //在第一次调用Update之前调用一次Start,即使取消激活,再激活也不会再执行 // 3.   在Start中做一些初始化操作 void Start(){ //一般做一些私有成员 } // 4.   每帧调用