zoukankan      html  css  js  c++  java
  • P4314 CPU监控

    传送门:https://www.luogu.com.cn/problem/P4314

    题意:

    给出 T 个数,E 个操作(T,E 10^5):

    Q X Y:询问从 X 到 Y 的当前最大值

    A X Y:询问从 X 到 Y 的历史最大值(出现过的最大数

    P X Y Z:将 X 到 Y 这段区间加 Z

    C X Y Z:将 X 到 Y 这段区间赋值为 Z

    这个题,第一反应就是线段树

    如果你是信心满满的用当前最大值及当前的标记维护历史最大值,你就会wa掉了

    仔细想想这个历史最大值,如果按照最初的写法,先add,再cover,那么当前sum还没有更新sum+add就被覆盖了,历史最大值就不准确了

    但你是不是又想在add之前把所有标记下放??

    这样的话lazy标记就失去意义了,时间复杂度翻倍的上升,会 tle8个点 应该

    呐 这个标记的方式就很巧妙了

    struct node 
    {
        int l,r,add,cov,sum,evsum,evadd,evcov,is_cov;
    }tree[maxn*4];
    基本的元素有l,r,add,cov
    我们后添加的有 evsum(历史最大值)evadd(历史添加的最大值),evcov(历史覆盖最大值),is_cov(是否被覆盖过)
    我们在下放标记更新sum的同时 用evxxx继续更新evsum
    而且是实时下放标记,没有判断条件
    重点是push_down,如何下放标记
     
    分类讨论
    1 加操作 对于他的两个儿子
    如果被覆盖过,那么覆盖cov之后再加add,就相当于是覆盖了cov+add,更新evcov,evsum
     //左儿子为例
    tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now<<1].cov+tree[now].evadd);
    tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].cov+tree[now].evadd);
    tree[now<<1].sum=tree[now<<1].cov=tree[now<<1].cov+tree[now].add;
    tree[now<<1].add=0;
    如果没有覆盖过,那就是加上一个add   更新evadd,evsum
     //左儿子为例
    tree[now<<1].evadd=max(tree[now<<1].evadd,tree[now<<1].add+tree[now].evadd); tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].sum+tree[now].evadd);
       tree[now<<1].add+=tree[now].add;
       tree[now<<1].sum+=tree[now].add;
    记得清空标记
     
    2 覆盖操作 对于他的两个儿子
    如果被覆盖过,覆盖了cov,同时取最大值更新evcov,evsum
    如果没有被覆盖过,把is_cov标记为1,把cov覆盖上去,更新evcov,evsum
     
    if(tree[now<<1].is_cov)//以左儿子为例
    {
        tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now].evcov);
    }
    else 
    {
        tree[now<<1].is_cov=1;
        tree[now<<1].evcov=tree[now].evcov;
    }
    tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now].evcov);
    tree[now<<1].cov=tree[now<<1].sum=tree[now].cov;
    tree[now<<1].add=0;
    关于怎么覆盖值得好好考虑,再就是要认清楚,他的本质是同时更新sum和evsum,把他们分开 自己考虑自己的就不会乱
     
    对于sum的更新就正常来就好了,每次的cover操作过后add也就该请零了
     
    240+行,这可真是我写除了模拟的最长代码,破了前天的记录
    虽然东西有点多,但思路很清晰
    仔细一点争取不用debug,不然绝对会崩溃的 (;´д`)ゞ
     
      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 #define ll long long
      4 #define lowbit(a) ((a) & -(a))
      5 #define clean(a, b) memset(a, b, sizeof(a))
      6 const int inf = 0x3f3f3f3f;
      7 const int maxn = 1e5 + 10;
      8 int _;
      9 
     10 /////////////////////////////////////////////////////////////////
     11 char s[10];
     12 int a[maxn];
     13 struct node 
     14 {
     15     int l,r,add,cov,sum,evsum,evadd,evcov,is_cov;
     16 }tree[maxn*4];
     17 void build(int l,int r,int now)
     18 {
     19     tree[now].l=l;
     20     tree[now].r=r;
     21     tree[now].sum=tree[now].evsum=-inf;
     22     if(l==r)
     23     {
     24         tree[now].sum=a[l];
     25         tree[now].evsum=a[l];
     26         return ;
     27     }
     28     int mid=(l+r)>>1;
     29     build(l,mid,now<<1);
     30     build(mid+1,r,now<<1|1);
     31     tree[now].evsum=tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum);
     32 }
     33 void push_down_add(int now)
     34 {
     35     if(tree[now<<1].is_cov) 
     36     {
     37         tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now<<1].cov+tree[now].evadd);
     38         tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].cov+tree[now].evadd);
     39         tree[now<<1].sum=tree[now<<1].cov=tree[now<<1].cov+tree[now].add;
     40         tree[now<<1].add=0;
     41     }
     42     else 
     43     {
     44         tree[now<<1].evadd=max(tree[now<<1].evadd,tree[now<<1].add+tree[now].evadd);
     45         tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now<<1].sum+tree[now].evadd);
     46         tree[now<<1].add+=tree[now].add;
     47         tree[now<<1].sum+=tree[now].add;
     48     }
     49     
     50     if(tree[now<<1|1].is_cov)
     51     {
     52         tree[now<<1|1].evcov=max(tree[now<<1|1].evcov,tree[now<<1|1].cov+tree[now].evadd);
     53         tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now<<1|1].cov+tree[now].evadd);
     54         tree[now<<1|1].sum=tree[now<<1|1].cov=tree[now<<1|1].cov+tree[now].add;
     55         tree[now<<1|1].add=0;
     56     }
     57     else 
     58     {
     59         tree[now<<1|1].evadd=max(tree[now<<1|1].evadd,tree[now<<1|1].add+tree[now].evadd);
     60         tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now<<1|1].sum+tree[now].evadd);
     61         tree[now<<1|1].add+=tree[now].add;
     62         tree[now<<1|1].sum+=tree[now].add;
     63     }
     64 
     65     tree[now].add=tree[now].evadd=0;
     66 
     67 }
     68 void push_down_cover(int now)
     69 {
     70     if(tree[now].is_cov)
     71     {
     72         if(tree[now<<1].is_cov)
     73         {
     74             tree[now<<1].evcov=max(tree[now<<1].evcov,tree[now].evcov);
     75         }
     76         else 
     77         {
     78             tree[now<<1].is_cov=1;
     79             tree[now<<1].evcov=tree[now].evcov;
     80         }
     81         tree[now<<1].evsum=max(tree[now<<1].evsum,tree[now].evcov);
     82         tree[now<<1].cov=tree[now<<1].sum=tree[now].cov;
     83         tree[now<<1].add=0;
     84         
     85         if(tree[now<<1|1].is_cov)
     86         {
     87             tree[now<<1|1].evcov=max(tree[now<<1|1].evcov,tree[now].evcov);
     88         }
     89         else 
     90         {
     91             tree[now<<1|1].is_cov=1;
     92             tree[now<<1|1].evcov=tree[now].evcov;
     93         }
     94         tree[now<<1|1].evsum=max(tree[now<<1|1].evsum,tree[now].evcov);
     95         tree[now<<1|1].cov=tree[now<<1|1].sum=tree[now].cov;
     96         tree[now<<1|1].add=0;
     97 
     98         tree[now].is_cov=tree[now].cov=tree[now].evcov=0;
     99     }
    100 }
    101 void push_down(int now)
    102 { 
    103     push_down_add(now);
    104     push_down_cover(now);  
    105 }
    106 void update(int l,int r,int x,int now)
    107 {
    108     if(l==tree[now].l&&r==tree[now].r)
    109     {
    110         if(tree[now].is_cov)
    111         {
    112             tree[now].evcov=max(tree[now].evcov,x);
    113         }
    114         else 
    115         {
    116             tree[now].is_cov=1;
    117             tree[now].evcov=x;
    118         }
    119         tree[now].evsum=max(tree[now].evsum,x);
    120         tree[now].cov=tree[now].sum=x;
    121         tree[now].add=0;
    122         return ;
    123     }
    124     push_down(now);
    125     int mid=(tree[now].l+tree[now].r)>>1;
    126     if(r<=mid) update(l,r,x,now<<1);
    127     else if(l>mid) update(l,r,x,now<<1|1);
    128     else 
    129     {
    130         update(l,mid,x,now<<1);
    131         update(mid+1,r,x,now<<1|1);
    132     }
    133     tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum);
    134     tree[now].evsum=max(tree[now].evsum,tree[now].sum);
    135 }
    136 void addition(int l,int r,int x,int now)
    137 {
    138     if(l==tree[now].l&&r==tree[now].r)
    139     {
    140         if(tree[now].is_cov) 
    141         {
    142             tree[now].evcov=max(tree[now].evcov,tree[now].cov+x);
    143             tree[now].evsum=max(tree[now].evsum,tree[now].cov+x);
    144             tree[now].cov=tree[now].sum=tree[now].cov+x;
    145             tree[now].add=0;
    146         }
    147         else 
    148         {
    149             tree[now].evadd=max(tree[now].evadd,tree[now].add+x);
    150             tree[now].evsum=max(tree[now].evsum,tree[now].sum+x);
    151             tree[now].add+=x;
    152             tree[now].sum+=x;
    153         }
    154         return ;
    155     }
    156     push_down(now);
    157     int mid=(tree[now].l+tree[now].r)>>1;
    158     if(r<=mid) addition(l,r,x,now<<1);
    159     else if(l>mid) addition(l,r,x,now<<1|1);
    160     else 
    161     {
    162         addition(l,mid,x,now<<1);
    163         addition(mid+1,r,x,now<<1|1);
    164     }
    165     tree[now].sum=max(tree[now<<1].sum,tree[now<<1|1].sum);
    166     tree[now].evsum=max(tree[now].evsum,tree[now].sum);
    167 }
    168 int query(int l,int r,int now)
    169 {
    170     if(l==tree[now].l&&r==tree[now].r)
    171     {
    172         return tree[now].sum;
    173     }
    174     push_down(now);
    175     int mid=(tree[now].l+tree[now].r)>>1;
    176     int maxx=-inf;
    177     if(r<=mid) maxx=max(maxx,query(l,r,now<<1));
    178     else if(l>mid) maxx=max(maxx,query(l,r,now<<1|1));
    179     else 
    180     {
    181         maxx=max(maxx,query(l,mid,now<<1));
    182         maxx=max(maxx,query(mid+1,r,now<<1|1));
    183     }
    184     return maxx;
    185 }
    186 int querymax(int l,int r,int now)
    187 {
    188     if(l==tree[now].l&&r==tree[now].r)
    189     {
    190         return tree[now].evsum;
    191     }
    192     push_down(now);
    193     int mid=(tree[now].l+tree[now].r)>>1;
    194     int maxx=-inf;
    195     if(r<=mid) maxx=max(maxx,querymax(l,r,now<<1));
    196     else if(l>mid) maxx=max(maxx,querymax(l,r,now<<1|1));
    197     else 
    198     {
    199         maxx=max(maxx,querymax(l,mid,now<<1));
    200         maxx=max(maxx,querymax(mid+1,r,now<<1|1));
    201     }
    202     return maxx;
    203 }
    204 ///////////////////////////////////////////////////////////////// 
    205 int main()
    206 {
    207     // freopen("in.in","r",stdin);
    208     int t,q;
    209     scanf("%d",&t);
    210     for(int i=1;i<=t;i++)
    211     {
    212         scanf("%d",&a[i]);
    213     }
    214     build(1,t,1);
    215     scanf("%d",&q);
    216     for(int i=1;i<=q;i++)
    217     {
    218         scanf("%s",s);
    219         int x,y,z;
    220         if(s[0]=='Q')//the max
    221         {
    222             scanf("%d%d",&x,&y);
    223             int ans=query(x,y,1);
    224             printf("%d
    ",ans);
    225         }
    226         if(s[0]=='A')//Ever largest
    227         {
    228             scanf("%d%d",&x,&y);
    229             int ans=querymax(x,y,1);
    230             printf("%d
    ",ans);
    231         }
    232         if(s[0]=='P')
    233         {
    234             scanf("%d%d%d",&x,&y,&z);
    235             addition(x,y,z,1);
    236         }
    237         if(s[0]=='C')
    238         {
    239             scanf("%d%d%d",&x,&y,&z);
    240             update(x,y,z,1);
    241         }
    242     }
    243     return 0;
    244 }
     
     
     
     
     
  • 相关阅读:
    去年一个百万级的小软件项目经验分享,20来个功能模块,项目不太好做有些棘手 zhuan zai
    软件架构师应该知道的97件事
    互联网创业需要哪些人? 留住人才,到一线去
    推荐:你可能需要的在线电子书 (转载)
    ios DOME(http://www.cocoachina.com/bbs/read.php?tid8101.html)
    在获得自信时常犯的三个错误 你的成功在于你每天养成的习惯
    Web开发性能优化总结 转载
    Android 移动平台概述
    互联网产品需求管理思考——统一需求管理
    Android 开发工具
  • 原文地址:https://www.cnblogs.com/YangKun-/p/12811197.html
Copyright © 2011-2022 走看看