zoukankan      html  css  js  c++  java
  • 洛谷题解P4314CPU监控--线段树

    题目链接

    https://www.luogu.org/problemnew/show/P4314

    https://www.lydsy.com/JudgeOnline/problem.php?id=3064

    分析

    其实我是在看吉司机线段树课件时看到这题很感兴趣就跑过来做

    显然如果数据小一点可以用分块什么的比较好搞

    但是这个数据范围可能用(log N)的数据结构更舒服一点

    怎么搞呢?请阅读国家集训队2016论文集之《区间最值操作与历史最值问题——杭州学军中学 吉如一》,对,就是我们敬爱可亲的吉司机.

    看不懂?实际上就是告诉我们维护6个(lazy)_(tag):

    1. (nmx)表示当前区间最大值,(add)表示当前区间加法标记,(set)表示当前区间赋值标记

    2. (pmx)表示当前区间历史最大值,(padd)表示当前区间在下传此标记前时历史最大加法标记,(pset)表示当前区间在下传此标记前历史最大赋值标记

    这样(lazy)_(tag)之间的合并就比较显然了

    然后再结合论文食用,或是看代码理解一下

    当然GXZlegend大佬使用吉司机的另一个方法也是可行的

    http://www.cnblogs.com/GXZlegend/p/8315275.html

    注意

    我查错又查了一个小时

    • 注意不要把(-inf)写成(inf)

    • (pushdown)时思维一定要清晰,注意是哪些标记会对其他标记产生影响

    代码

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <cctype>
    #include <iostream>
    #define ll long long 
    #define ri register int 
    using std::max;
    const int inf=0x3f3f3f3f;
    const int maxn=100005;
    template <class T>inline void read(T &x){
      x=0;int ne=0;char c;
      while(!isdigit(c=getchar()))ne=c=='-';
      x=c-48;
      while(isdigit(c=getchar()))x=(x<<3)+(x<<1)+c-48;
      x=ne?-x:x;return ;
    }
    int n;
    int nmx[maxn<<2],add[maxn<<2],set[maxn<<2];
    int pmx[maxn<<2],padd[maxn<<2],pset[maxn<<2];
    int num[maxn];
    int L,R,dta;
    void build(int now,int l,int r){
      set[now]=nmx[now]=pmx[now]=pset[now]=-inf;
      padd[now]=add[now]=0;
      if(l==r){
          nmx[now]=pmx[now]=num[l];
          return ;
      }
      int mid=(l+r)>>1;
      build(now<<1,l,mid);
      build(now<<1|1,mid+1,r);
      nmx[now]=pmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
      return ;
    }
    inline void pushdown(int now){
      if(padd[now]){
          pmx[now<<1]=max(pmx[now<<1],nmx[now<<1]+padd[now]);
          if(set[now<<1]!=-inf)
              pset[now<<1]=max(pset[now<<1],set[now<<1]+padd[now]);
          else 
              padd[now<<1]=max(padd[now<<1],add[now<<1]+padd[now]);
          pmx[now<<1|1]=max(pmx[now<<1|1],nmx[now<<1|1]+padd[now]);
          if(set[now<<1|1]!=-inf)
              pset[now<<1|1]=max(pset[now<<1|1],set[now<<1|1]+padd[now]);
          else 
              padd[now<<1|1]=max(padd[now<<1|1],add[now<<1|1]+padd[now]);
          padd[now]=0;
      }
      if(pset[now]!=-inf){
          pmx[now<<1]=max(pmx[now<<1],pset[now]);
          pset[now<<1]=max(pset[now<<1],pset[now]);
          pmx[now<<1|1]=max(pmx[now<<1|1],pset[now]);
          pset[now<<1|1]=max(pset[now<<1|1],pset[now]);
          pset[now]=-inf;
      }
      if(add[now]){
          nmx[now<<1]+=add[now];
          pmx[now<<1]=max(pmx[now<<1],nmx[now<<1]);
          if(set[now<<1]!=-inf){
              set[now<<1]+=add[now];
              pset[now<<1]=max(pset[now<<1],set[now<<1]);
          }
          else {
              add[now<<1]+=add[now];
              padd[now<<1]=max(padd[now<<1],add[now<<1]);
          }
          nmx[now<<1|1]+=add[now];
          pmx[now<<1|1]=max(pmx[now<<1|1],nmx[now<<1|1]);
          if(set[now<<1|1]!=-inf){
              set[now<<1|1]+=add[now];
              pset[now<<1|1]=max(pset[now<<1|1],set[now<<1|1]);
          }
          else {
              add[now<<1|1]+=add[now];
              padd[now<<1|1]=max(padd[now<<1|1],add[now<<1|1]);
          }
          add[now]=0;
      }
      if(set[now]!=-inf){
          nmx[now<<1]=set[now];
          pmx[now<<1]=max(pmx[now<<1],nmx[now<<1]);
          set[now<<1]=set[now];
          pset[now<<1]=max(pset[now<<1],set[now<<1]);
          nmx[now<<1|1]=set[now];
          pmx[now<<1|1]=max(pmx[now<<1|1],nmx[now<<1|1]);
          set[now<<1|1]=set[now];
          pset[now<<1|1]=max(pset[now<<1|1],set[now<<1|1]);
          set[now]=-inf;
          add[now<<1]=add[now<<1|1]=0;
      }
      return ;
    }
    void update_add(int now,int l,int r){
      if(L<=l&&r<=R){
          nmx[now]+=dta;
          pmx[now]=max(pmx[now],nmx[now]);
          if(set[now]!=-inf){
              set[now]+=dta;
              pset[now]=max(pset[now],set[now]);
          }
          else{
              add[now]+=dta;
              padd[now]=max(padd[now],add[now]);
          }
          return ;
      }
      int mid=(l+r)>>1;
      pushdown(now);
      if(L<=mid)update_add(now<<1,l,mid);
      if(mid<R)update_add(now<<1|1,mid+1,r);
      nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
      pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
      return ;
    }
    void update_set(int now,int l,int r){
      if(L<=l&&r<=R){
          nmx[now]=dta;
          pmx[now]=max(pmx[now],dta);
          set[now]=dta;
          pset[now]=max(pset[now],dta);
          add[now]=0;
          return ;
      }
      int mid=(l+r)>>1;
      pushdown(now);
      if(L<=mid)update_set(now<<1,l,mid);
      if(mid<R)update_set(now<<1|1,mid+1,r);
      nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
      pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
      return;
    }
    int query_now(int now,int l,int r){
      if(L<=l&&r<=R){
          return nmx[now];
      }
      int ans=-inf,mid=(l+r)>>1;
      pushdown(now);
      if(L<=mid)ans=max(ans,query_now(now<<1,l,mid));
      if(mid<R)ans=max(ans,query_now(now<<1|1,mid+1,r));
      nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
      pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
      return ans;
    }
    int query_history(int now,int l,int r){
      if(L<=l&&r<=R){
          return pmx[now];
      }
      int ans=-inf,mid=(l+r)>>1;
      pushdown(now);
      if(L<=mid)ans=max(ans,query_history(now<<1,l,mid));
      if(mid<R)ans=max(ans,query_history(now<<1|1,mid+1,r));
      nmx[now]=max(nmx[now<<1],nmx[now<<1|1]);
      pmx[now]=max(pmx[now<<1],pmx[now<<1|1]);
      return ans;
    }
    int q;
    int main(){
      int x,y,z;
      char opt[5];
      read(n);
      for(ri i=1;i<=n;i++)read(num[i]);
      build(1,1,n);
      read(q);
      while(q--){
         scanf("%s",opt);
         read(x),read(y);
         L=x,R=y;
         if(opt[0]=='Q'){
             printf("%d
    ",query_now(1,1,n));
         }
         else if(opt[0]=='A'){
             printf("%d
    ",query_history(1,1,n));
         }
         else if(opt[0]=='P'){
             read(dta);
             update_add(1,1,n);
         }
         else{
             read(dta);
             update_set(1,1,n);
         }
      }
      return 0;
    }
    

    目前洛谷rank 2,在BZOJ上被吊打

  • 相关阅读:
    2019秋季 关于C语言指针等探索
    第四次作业
    第三次作业
    错误总结
    第二次作业
    第一次随笔
    Linux Mint安装Docker踩坑指南
    浅论Javascript在汽车信号测试中的应用
    [瞎玩儿系列] 使用SQL实现Logistic回归
    MongoDB的账户与权限管理及在Python与Java中的登录
  • 原文地址:https://www.cnblogs.com/Rye-Catcher/p/9387887.html
Copyright © 2011-2022 走看看