• TZOJ 4021 Ugly Problem(线段树区间子段最大)


    描述

    给定一个序列A[0],A[1],…A[N-1],要求找到p0,p1,p2,p3使得A[p0]+A[p0+1]+…+A[p1] + A[p2]+A[p2+1]+…+A[p3]最大(0<=p0<=p1<p2<=p3<N)。你只需要求出这个最大值就可以。

    输入

    输入的第一行为一个数N(2<=N<=10000),接下来的一行为N个整数(-100<A[i]<100)。

    输出

    输出一个整数表示最大值。

    样例输入

    5
    -1 -2 -4 -5 4

    样例输出

    3

    题意

    如上。

    题解

    枚举分割点,求左区间最大子段和和到右区间最大字段和。

    区间最大值段和是一个经典题,线段树维护。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=10005;
     4 struct node{
     5     int sum,lmax,rmax,lrs; 
     6 }tree[maxn<<2];
     7 void pushup(int x){
     8     tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
     9     tree[x].lmax=max(tree[x<<1].lmax,tree[x<<1|1].lmax+tree[x<<1].sum);
    10     tree[x].rmax=max(tree[x<<1|1].rmax,tree[x<<1].rmax+tree[x<<1|1].sum);
    11     tree[x].lrs=max(max(tree[x<<1].lrs,tree[x<<1|1].lrs),tree[x<<1].rmax+tree[x<<1|1].lmax);
    12 }
    13 void build(int l,int r,int p){
    14     if(l==r){
    15         scanf("%d",&tree[p].sum);
    16         tree[p].lmax=tree[p].lrs=tree[p].rmax=tree[p].sum;
    17         return;
    18     }
    19     int mid=(l+r)>>1;
    20     build(l,mid,p<<1);
    21     build(mid+1,r,p<<1|1);
    22     pushup(p);
    23 }
    24 void update(int k,int v,int l,int r,int p){
    25     if(l==r){
    26         tree[p].lmax=tree[p].lrs=tree[p].rmax=tree[p].sum=v;
    27         return;
    28     }
    29     int mid=(l+r)>>1;
    30     if(k<=mid)update(k,v,l,mid,p<<1);
    31     else update(k,v,mid+1,r,p<<1|1);
    32     pushup(p);
    33 }
    34 node quert(int L,int R,int l,int r,int p){
    35     if(L<=l&&r<=R)return tree[p];
    36     int mid=(l+r)>>1;
    37     node vis,f1,f2;
    38     vis.sum=0;
    39     if(L<=mid)vis=f1=quert(L,R,l,mid,p<<1);
    40     if(R>mid)vis=f2=quert(L,R,mid+1,r,p<<1|1);
    41     if(L<=mid&&R>mid){
    42         vis.sum=f1.sum+f2.sum;
    43         vis.lmax=max(f1.lmax,f1.sum+f2.lmax);
    44         vis.rmax=max(f2.rmax,f2.sum+f1.rmax);
    45         vis.lrs=max(max(f1.lrs,f2.lrs),f1.rmax+f2.lmax);
    46     }
    47     return vis;
    48 }
    49 int main(){
    50     int n,maxx=-1e9;
    51     scanf("%d",&n);
    52     build(1,n,1);
    53     for(int i=1;i<n;i++)
    54         maxx=max(quert(1,i,1,n,1).lrs+quert(i+1,n,1,n,1).lrs,maxx);
    55     printf("%d
    ",maxx);
    56     return 0;
    57 }
  • 相关阅读:
    浏览器组成
    Go!!!
    产假计算器地址
    flex 纵向布局,垂直换行,没有撑开父盒子宽度,求解??
    毕业档案
    进程与线程
    事件循环
    回调地狱
    错误优先回调
    组件 v-if 小心哦
  • 原文地址:https://www.cnblogs.com/taozi1115402474/p/11637660.html
Copyright © 2020-2023  润新知