• 暑假集训Day4 E(线段树好题)


    题目链接在本地

    这道题如果按照题目意思去算c_i的话每一步都会是 O(n) 的复杂度,而且并不知道每一步的操作对后续的影响是什么,很显然不能这么做

    这种情况下我们要考虑到要将c_i化成一个和 1...i 或者 i...n 有关的式子(i...n的情况可以用1...n减去1...i-1来解决),这样才能用数据结构的方法去解决

    将c_x展开来看的话,我们可以发现c_x=max(a_i+b_i+b_(i+1)+b_(i+2)+...+b_x) (i=1...x) 到这一步已经有些眉目了,我们可以建立一棵最大值线段树,但是我们发现这个b_i的求和还是有些难度的,仔细观察可以发现是上一段说到的 i...n 的情况,所以式子可以化简为 c_x=(b_1+...+b_x) + max (a_i - (b_1+...+b_i)) (i=1...x) 这样我们就把 i...n 的情况转化为1...i的情况,就可以用树状数组的方法比较容易的求出来。

    上上段说到的这个简化提取通项的思想是非常重要的,不仅是在数据结构中有用,因为如果不简化取通项,永远只能关注到前后两项,根本找不出思路,这种求通项的思想在很多问题中都具有广泛应用。

     1 #include "bits/stdc++.h"
     2 #define lson rt<<1,l,m
     3 #define rson rt<<1|1,m+1,r
     4 using namespace std;
     5 typedef long long LL;
     6 const int MAX=2e5+5;
     7 LL n,cas;
     8 LL a[MAX],b[MAX],s[MAX];
     9 LL t[MAX<<2],la[MAX<<2];
    10 void update(LL x,LL y){for (;x<=n;x+=(x&-x)) s[x]+=y;}
    11 LL search(LL x){LL an=0;for (;x>0;x-=(x&-x)) an+=s[x];return an;}
    12 void PushDown(LL rt){
    13     if (la[rt]){
    14         t[rt<<1]+=la[rt];
    15         t[rt<<1|1]+=la[rt];
    16         la[rt<<1]+=la[rt];
    17         la[rt<<1|1]+=la[rt];
    18         la[rt]=0;
    19     }
    20 }
    21 void PushUp(LL rt){
    22     t[rt]=max(t[rt<<1],t[rt<<1|1]);
    23 }
    24 void build(LL rt,LL l,LL r){
    25     la[rt]=0;
    26     if (l==r){
    27         t[rt]=a[l]-search(l);
    28         return;
    29     }
    30     LL m=(l+r)>>1;
    31     build(lson);
    32     build(rson);
    33     PushUp(rt);
    34 }
    35 void upd(LL rt,LL l,LL r,LL x,LL y,LL z){
    36     if (x<=l && r<=y){
    37         la[rt]+=z;
    38         t[rt]+=z;
    39         return;
    40     }
    41     LL m=(l+r)>>1;
    42     PushDown(rt);
    43     if (x<=m)
    44         upd(lson,x,y,z);
    45     if (y>m)
    46         upd(rson,x,y,z);
    47     PushUp(rt);
    48 }
    49 LL srch(LL rt,LL l,LL r,LL x,LL y){
    50     if (x<=l && r<=y) return t[rt];
    51     LL m=(l+r)>>1,an=-10000000000000000ll;
    52     PushDown(rt);
    53     if (x<=m)
    54         an=max(an,srch(lson,x,y));
    55     if (y>m)
    56         an=max(an,srch(rson,x,y));
    57     return an;
    58 }
    59 int main(){
    60 //    freopen ("e.in","r",stdin);
    61 //    freopen ("e.out","w",stdout);
    62     LL i,j,x,y,z;
    63     while (scanf("%lld%lld",&n,&cas)!=EOF){
    64         for (i=1;i<=n;i++){
    65             scanf("%lld",a+i);
    66             s[i]=0;
    67         }
    68         for (i=1;i<=n;i++){
    69             scanf("%lld",b+i);
    70             update(i,b[i]);
    71         }
    72         build(1,1,n);
    73         while (cas--){
    74             scanf("%lld",&x);
    75             if (x==1){
    76                 scanf("%lld%lld",&y,&z);
    77                 upd(1,1,n,y,y,z-a[y]);
    78                 a[y]=z;
    79             }
    80             if (x==2){
    81                 scanf("%lld%lld",&y,&z);
    82                 update(y,z-b[y]);
    83                 upd(1,1,n,y,n,b[y]-z);
    84                 b[y]=z;
    85             }
    86             if (x==3){
    87                 scanf("%lld",&y);
    88                 printf("%lld\n",search(y)+max(0ll,srch(1,1,n,1,y)));
    89             }
    90         }
    91     }
    92     return 0;
    93 }
    94  
  • 相关阅读:
    洛谷P1120信息奥赛一本通1442 小木棍
    洛谷P1378 油滴扩展
    洛谷P1156 垃圾陷阱
    mybatis-Plus 实践篇之逆向工程
    Interceptor的使用及探究
    mysql,oracle,sqlServer 元数据查询
    navicat premium15免费版安装说明(附工具)
    打印日志你真的会吗?
    线程基础知识-必知必会
    空间复杂度&时间复杂度
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/16461141.html
Copyright © 2020-2023  润新知