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 }
     
     
     
     
     
  • 相关阅读:
    HDU 1501 Zipper(DFS)
    HDU 2181 哈密顿绕行世界问题(DFS)
    HDU 1254 推箱子(BFS)
    HDU 1045 Fire Net (DFS)
    HDU 2212 DFS
    HDU 1241Oil Deposits (DFS)
    HDU 1312 Red and Black (DFS)
    HDU 1010 Tempter of the Bone(DFS+奇偶剪枝)
    HDU 1022 Train Problem I(栈)
    HDU 1008 u Calculate e
  • 原文地址:https://www.cnblogs.com/YangKun-/p/12811197.html
Copyright © 2011-2022 走看看