• 「在更」初涉历史最值线段树


    历史最值线段树好像听上去很简单,多带几个参数就可以了? 吗?

    历史最值线段树

    正如其名,「历史最值线段树」记录的是区间内的历史最值。

    HistoricalMaxVal == max(Tree[i].val)?

    听上去是不是很简单啊?是不是我们每次记录一下max就好了啊?

    好吧不讲这个正常人不会认可的想法了。

    记录当前最大值mx?

    那么我们记录一下当前区间的最大值$mx$,然后每一次操作这个区间的时候用$HistoricalMaxVal=max(mx+add)$更新一下怎么样?

    是的,这样对于线段树单个节点来说正确性是有了。但是我们怎么向下传递呢?

    我们都知道线段树区间操作为了效率是要$pushdown$操作的。但如果按照这种思路,我们只能够更新区间而无法向下传递!

    可能有点抽象,举个例子:

    a[]:1 2 3 4 5
    add 1 5 15
    add 1 5 -15
    query 3 5

    这里我们先对$[1,5]$加上15,再对$[1,5]$减去15,最后查询$[3,5]$的历史最大值。

    如果对于每一个区间我们只记录$mx,hisMx$这两个数,上面例子里的前两个操作都只是对于线段树的root($[1,5]$这个区间)操作,并且最终记录下来$add=0,his=15$。可是$[1,5]$记录下来的正确的最大值又有什么用呢?我们查询的是$[3,5]$,这样一来查询出来的答案就变成$5$了。

    几道例题

    bzoj3064: Tyvj 1518 CPU监控

    Description

    Bob需要一个程序来监视CPU使用率。这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事。
    Bob会干很多事,除了跑暴力程序看视频之外,还会做出去玩玩和用鼠标乱点之类的事,甚至会一脚踢掉电源……这些事有的会让做这件事的这段时间内CPU使用率增加或减少一个值;有的事还会直接让CPU使用率变为一个值。
    当然Bob会询问:在之前给出的事件影响下,CPU在某段时间内,使用率最高是多少。有时候Bob还会好奇地询问,在某段时间内CPU曾经的最高使用率是多少。
    为了使计算精确,使用率不用百分比而用一个整数表示。
    不保证Bob的事件列表出了莫名的问题,使得使用率为负………………

    Input

    第一行一个正整数T,表示Bob需要监视CPU的总时间。
    然后第二行给出T个数表示在你的监视程序执行之前,Bob干的事让CPU在这段时间内每个时刻的使用率达已经达到了多少。
    第三行给出一个数E,表示Bob需要做的事和询问的总数。
    接下来E行每行表示给出一个询问或者列出一条事件:
    Q X Y:询问从X到Y这段时间内CPU最高使用率
    A X Y:询问从X到Y这段时间内之前列出的事件使CPU达到过的最高使用率
    P X Y Z:列出一个事件这个事件使得从X到Y这段时间内CPU使用率增加Z
    C X Y Z:列出一个事件这个事件使得从X到Y这段时间内CPU使用率变为Z
    时间的单位为秒,使用率没有单位。
    X和Y均为正整数(X<=Y),Z为一个整数。
    从X到Y这段时间包含第X秒和第Y秒。
    保证必要运算在有符号32位整数以内。 

    Output

    对于每个询问,输出一行一个整数回答。

    HINT 

    数据分布如下:
    第1、2个数据保证T和E均小于等于1000
    第3、4个数据保证只有Q类询问
    第5、6个数据保证只有C类事件
    第7、8个数据保证只有P类事件
    全部数据保证T和E均小于等于100000


    题目分析

    虽然说是板子题但是调了一晚上……

    先把代码挂这里

    注释掉的部分不是调试部分,就是打挂的细节处理。

      1 #include<bits/stdc++.h>
      2 const int INF = 2147483647;
      3 const int maxn = 100035;
      4 
      5 struct node
      6 {
      7     int hisMx,mx;
      8     int cg,add,cgMx,addMx;
      9     bool ce;
     10 }f[maxn<<2];
     11 int n,m;
     12 
     13 int read()
     14 {
     15     int num = 0;
     16     char ch = getchar();
     17     bool fl = 0;
     18     for (; !isdigit(ch); ch = getchar())
     19         if (ch=='-') fl = 1;
     20     for (; isdigit(ch); ch = getchar())
     21         num = (num<<1)+(num<<3)+ch-48;
     22     if (fl) num = -num;
     23     return num;
     24 }
     25 void pushup(int rt)
     26 {
     27     f[rt].mx = std::max(f[rt<<1].mx, f[rt<<1|1].mx);
     28     // f[rt].hisMx = std::max(f[rt].mx, f[rt].hisMx);
     29     f[rt].hisMx = std::max(f[rt<<1].hisMx, f[rt<<1|1].hisMx);
     30 }
     31 void pushdown(int rt)
     32 {
     33     // printf("pushdownINFO:
    ");
     34     for (int i=0; i<=1; i++)
     35     {
     36         int x = rt<<1|i;
     37         f[x].hisMx = std::max(f[x].hisMx, std::max(f[rt].cgMx, f[x].mx+f[rt].addMx));
     38         if (f[x].cg!=-INF) f[x].cgMx = std::max(f[x].cgMx, f[x].cg+f[rt].addMx);
     39         else f[x].addMx = std::max(f[x].addMx, f[x].add+f[rt].addMx);
     40         // if (f[rt].cg){
     41         //     f[x].add = 0;
     42         //     f[x].ce = 1, f[x].mx = f[x].cg = f[rt].cg;
     43         //     f[x].cgMx = std::max(f[x].cg, f[x].cgMx);
     44         // }
     45         // if (f[rt].add){
     46         //     f[x].add += f[rt].add;
     47         // }
     48         // f[x].hisMx = std::max(f[x].hisMx, std::max(f[x].cgMx, f[x].mx+f[x].addMx));
     49         if (f[rt].add){
     50             if (f[x].cg!=-INF) f[x].cg += f[rt].add;
     51             else f[x].add += f[rt].add;
     52             f[x].mx += f[rt].add;
     53         }
     54         // if (f[rt].ce){
     55         if (f[rt].cg!=-INF){
     56             f[x].mx = f[x].cg = f[rt].cg;
     57             f[x].add = 0;
     58         }
     59         f[x].addMx = std::max(f[x].addMx, f[x].add);
     60         f[x].cgMx = std::max(f[x].cgMx, std::max(f[x].cg, f[rt].cgMx));
     61         // printf("%d: addMx:%d cgMx:%d hisMx:%d
    ",i,f[x].addMx,f[x].cgMx,f[x].hisMx);
     62     }
     63     // puts("");
     64     f[rt].add = f[rt].addMx = 0;
     65     f[rt].ce = 0, f[rt].cg = f[rt].cgMx = -INF;
     66 }
     67 void build(int rt, int l, int r)
     68 {
     69     f[rt].cg = f[rt].cgMx = -INF;
     70     if (l==r){
     71         f[rt].hisMx = f[rt].mx = read();
     72         // f[rt].cg = f[rt].cgMx = -INF;
     73         return;
     74     }
     75     int mid = (l+r)>>1;
     76     build(rt<<1, l, mid), build(rt<<1|1, mid+1, r);
     77     pushup(rt);
     78     return;
     79 }
     80 int queryMx(int rt, int L, int R, int l, int r)
     81 {
     82     if (l!=r) pushdown(rt);
     83     if (L <= l&&r <= R) return f[rt].mx;
     84     int mid = (l+r)>>1, ret = -INF;
     85     if (L <= mid) ret = std::max(ret, queryMx(rt<<1, L, R, l, mid));
     86     if (R > mid) ret = std::max(ret, queryMx(rt<<1|1, L, R, mid+1, r));
     87     return ret;
     88 }
     89 int queryHis(int rt, int L, int R, int l, int r)
     90 {
     91     if (l!=r) pushdown(rt);
     92     if (L <= l&&r <= R) return f[rt].hisMx;
     93     int mid = (l+r)>>1, ret = -INF;
     94     if (L <= mid) ret = std::max(ret, queryHis(rt<<1, L, R, l, mid));
     95     if (R > mid) ret = std::max(ret, queryHis(rt<<1|1, L, R, mid+1, r));
     96     return ret;
     97 }
     98 void updateAdd(int rt, int L, int R, int l, int r, int c)
     99 {
    100     if (l!=r) pushdown(rt);
    101     if (L <= l&&r <= R){
    102         f[rt].add += c, f[rt].mx += c;
    103         // f[rt].addMx = std::max(f[rt].addMx, f[rt].add);
    104         f[rt].addMx += c;
    105         f[rt].hisMx = std::max(f[rt].mx, f[rt].hisMx);
    106         return;
    107     }
    108     int mid = (l+r)>>1;
    109     if (L <= mid) updateAdd(rt<<1, L, R, l, mid, c);
    110     if (R > mid) updateAdd(rt<<1|1, L, R, mid+1, r, c);
    111     pushup(rt);
    112     return;
    113 }
    114 void updateCover(int rt, int L, int R, int l, int r, int c)
    115 {
    116     if (l!=r) pushdown(rt);
    117     if (L <= l&&r <= R){
    118         // f[rt].add = 0;
    119         f[rt].ce = 1;
    120         f[rt].cgMx = f[rt].mx = f[rt].cg = c;
    121         f[rt].hisMx = std::max(f[rt].mx, f[rt].hisMx);
    122         return;
    123     }
    124     int mid = (l+r)>>1;
    125     if (L <= mid) updateCover(rt<<1, L, R, l, mid, c);
    126     if (R > mid) updateCover(rt<<1|1, L, R, mid+1, r, c);
    127     pushup(rt);
    128     return;
    129 }
    130 int main()
    131 {
    132     n = read();
    133     build(1, 1, n);
    134     m = read();
    135     while (m--)
    136     {
    137         char ch[5];
    138         scanf("%s",ch);
    139         int x = read(), y = read(), z;
    140         if (ch[0]=='Q')
    141             printf("%d
    ",queryMx(1, x, y, 1, n));
    142         else if (ch[0]=='A')
    143             printf("%d
    ",queryHis(1, x, y, 1, n));
    144         else{
    145             z = read();
    146             if (ch[0]=='P')
    147                 updateAdd(1, x, y, 1, n, z);
    148             else updateCover(1, x, y, 1, n, z);
    149         }
    150     }
    151     return 0;
    152 }
  • 相关阅读:
    html标签
    正则表达式判断号码靓号类型
    power函数:求底的n次幂
    php5.3的新特性
    xml方式操作txt文件
    什么是闭包?
    php设计模式单例模式
    面试总结
    统计ip代码
    XSL语言学习
  • 原文地址:https://www.cnblogs.com/antiquality/p/9206223.html
Copyright © 2020-2023  润新知