zoukankan      html  css  js  c++  java
  • 洛谷 P4513 小白逛公园-区间最大子段和-分治+线段树区间合并(单点更新、区间查询)

    P4513 小白逛公园

    题目背景

    小新经常陪小白去公园玩,也就是所谓的遛狗啦…

    题目描述

    在小新家附近有一条“公园路”,路的一边从南到北依次排着nn个公园,小白早就看花了眼,自己也不清楚该去哪些公园玩了。

    一开始,小白就根据公园的风景给每个公园打了分-.-。小新为了省事,每次遛狗的时候都会事先规定一个范围,小白只可以选择第aa个和第bb个公园之间(包括aa、bb两个公园)选择连续的一些公园玩。小白当然希望选出的公园的分数总和尽量高咯。同时,由于一些公园的景观会有所改变,所以,小白的打分也可能会有一些变化。

    那么,就请你来帮小白选择公园吧。

    输入输出格式

    输入格式:

    第一行,两个整数NN和MM,分别表示表示公园的数量和操作(遛狗或者改变打分)总数。
    接下来NN行,每行一个整数,依次给出小白 开始时对公园的打分。
    接下来MM行,每行三个整数。第一个整数KK,11或22。

    • K=1K=1表示,小新要带小白出去玩,接下来的两个整数aa和bb给出了选择公园的范围(1≤a,b≤N1a,bN)。测试数据可能会出现a>ba>b的情况,需要进行交换;
    • K=2K=2表示,小白改变了对某个公园的打分,接下来的两个整数pp和ss,表示小白对第pp个公园的打分变成了ss(1≤p≤N1pN)。
      其中,1≤N≤500 0001N500000,1≤M≤100 0001M100000,所有打分都是绝对值不超过10001000的整数。

    输出格式:

    小白每出去玩一次,都对应输出一行,只包含一个整数,表示小白可以选出的公园得分和的最大值。

    输入输出样例

    输入样例#1: 复制
    5 3
    1 2 -3 4 5
    1 2 3
    2 2 -1
    1 2 3
    输出样例#1: 复制
    2
    -1

    区间最大子段和,正常的区间不变的可以分治或者dp啥的,线段树的就维护最大前缀和,最大后缀和,之类的。

    具体的代码写了注释。。。

    代码:

     1 //线段树-分治+区间合并
     2 //区间最大子段和有三种情况:
     3 //1.左子树最大子段和
     4 //2.右子树最大子段和
     5 //3.左子树的最大后缀和+右子树的最大前缀和
     6 
     7 //思路特别简单,但是写自己顺手的模板改的时间有点久,最后选择了这种方式,其他int返回值的函数有代码重复的操作
     8 
     9 #include<bits/stdc++.h>
    10 using namespace std;
    11 typedef long long ll;
    12 const int maxn=5e5+10;
    13 
    14 #define lson l,m,rt<<1
    15 #define rson m+1,r,rt<<1|1
    16 
    17 struct Tree{
    18     int pre,suf,sub,val;//pre为当前区间最大前缀和,suf为当前区间最大后缀和,sub为当前区间最大子段和,val为当前区间的和
    19 }tree[maxn<<2];
    20 
    21 Tree pushup(Tree l,Tree r)
    22 {
    23     Tree rt;
    24     rt.pre=max(l.pre,l.val+r.pre);//当前区间的最大前缀和:左子树的最大前缀和 or 左子树的和+右子树的最大前缀和
    25     rt.suf=max(r.suf,r.val+l.suf);//当前区间的最大后缀和:右子树的最大后缀和 or 右子树的和+左子树的最大后缀和
    26     rt.sub=max(max(l.sub,r.sub),l.suf+r.pre);//当前区间的最大子段和:左子树的最大子段和 or 右子树的最大子段和 or 左子树的最大后缀和+右子树的最大前缀和
    27     rt.val=l.val+r.val;//当前区间的和:左子树的和+右子树的和
    28     return rt;
    29 }
    30 
    31 void build(int l,int r,int rt)
    32 {
    33     if(l==r){
    34         scanf("%d",&tree[rt].val);
    35         tree[rt].pre=tree[rt].suf=tree[rt].sub=tree[rt].val;
    36         return ;
    37     }
    38 
    39     int m=(l+r)>>1;
    40     build(lson);
    41     build(rson);
    42     tree[rt]=pushup(tree[rt<<1],tree[rt<<1|1]);
    43 }
    44 
    45 void update(int pos,int c,int l,int r,int rt)
    46 {
    47     if(l==r){
    48         tree[rt].pre=tree[rt].suf=tree[rt].sub=tree[rt].val=c;
    49         return ;
    50     }
    51 
    52     int m=(l+r)>>1;
    53     if(pos<=m) update(pos,c,lson);
    54     if(pos> m) update(pos,c,rson);
    55     tree[rt]=pushup(tree[rt<<1],tree[rt<<1|1]);
    56 }
    57 
    58 Tree query(int L,int R,int l,int r,int rt)
    59 {
    60     if(L<=l&&r<=R){
    61         return tree[rt];
    62     }
    63 
    64     int m=(l+r)>>1;
    65     Tree ret,lret,rret;
    66     int flag1=0,flag2=0;
    67     if(L<=m) {lret=query(L,R,lson);flag1=1;}
    68     if(R> m) {rret=query(L,R,rson);flag2=1;}
    69 
    70     if(flag1&&flag2) ret=pushup(lret,rret);//合并
    71     else if(flag1) ret=lret;
    72     else if(flag2) ret=rret;
    73     return ret;
    74 }
    75 
    76 int main()
    77 {
    78     int n,m;
    79     scanf("%d%d",&n,&m);
    80     build(1,n,1);
    81     for(int i=1;i<=m;i++){
    82         int op;
    83         scanf("%d",&op);
    84         if(op==1){
    85             int l,r;
    86             scanf("%d%d",&l,&r);
    87             if(l>r) swap(l,r);
    88             Tree ans=query(l,r,1,n,1);
    89             printf("%d
    ",ans.sub);
    90         }
    91         else{
    92             int p,s;
    93             scanf("%d%d",&p,&s);
    94             update(p,s,1,n,1);
    95         }
    96     }
    97     return 0;
    98 }
  • 相关阅读:
    cef 依赖的文件 libcef
    ubuntu 添加新分区,并挂载/home
    x509 证书链验证
    chromium调试
    Chromium智能指针使用指南
    具有扩展主密钥时SSL/TLS的主密钥计算
    OpenSSL解惑2:如何强制选择协议的版本
    基于Gmssl的SM2加解密算法Demo
    漫谈TLS nonce
    VS2015动态库静态加载时指定动态库位置的方法
  • 原文地址:https://www.cnblogs.com/ZERO-/p/10679858.html
Copyright © 2011-2022 走看看