传送门

线段树好题。

维护区间加,区间覆盖,区间最大,区间历史最大。

这个东西在国家集训队2016论文集之《区间最值操作与历史最值问题——杭州学军中学 吉如一》中讲的已经很详细了。

简单来说是这样的:

我们先考虑没有区间覆盖的情况,如果只有区间加的话,我们维护一个标记history" role="presentation" style="position: relative;">historyhistory_add" role="presentation" style="position: relative;">addadd来表示当前区间在上一次区间加之后最大的历史加标记,这样的话可以用这个标记来更新历史最大值。

然后如果有了区间覆盖操作,不难证明一个区间在区间覆盖之后每一次区间加操作都相当于一次区间覆盖操作,因此我们类似地维护一个historyset" role="presentation" style="position: relative;">historysethistoryset来对历史最大值进行更新。

代码(add[0]" role="presentation" style="position: relative;">add[0]add[0]->普通区间加标记,set[0]" role="presentation" style="position: relative;">set[0]set[0]->普通覆盖标记,add[1]" role="presentation" style="position: relative;">add[1]add[1]->历史区间加标记,set[1]" role="presentation" style="position: relative;">set[1]set[1]->历史覆盖标记):

#include<iostream>
#include<cstring>
#include<cstdio>
#define inf 0x3f3f3f3f
#define N 100005
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
inline int read(){
    int ans=0,w=1;
    char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans*w;
}
inline void write(int x){
    if(x<0)putchar('-'),x=-x;
    if(x>9)write(x/10);
    putchar((x%10)^48);
}
int a[N],n,q;
struct Node{int l,r,add[2],set[2],his,mx;}T[N<<2];
inline int max(int a,int b){return a>b?a:b;}
inline void pushup(int p){T[p].mx=max(T[lc].mx,T[rc].mx),T[p].his=max(T[lc].his,T[rc].his);}
inline void pushadd(int p,int v){
    T[p].his=max(T[p].his,T[p].mx+=v);
    if(T[p].set[0]!=-inf)T[p].set[1]=max(T[p].set[1],T[p].set[0]+=v);
    else T[p].add[1]=max(T[p].add[1],T[p].add[0]+=v);
}
inline void pushset(int p,int v){
    T[p].set[1]=max(T[p].set[1],T[p].set[0]=v),T[p].add[0]=0;
    T[p].his=max(T[p].his,T[p].mx=v);
}
inline void his_add(int p,int v){
    T[p].his=max(T[p].his,T[p].mx+v);
    if(T[p].set[0]!=-inf)T[p].set[1]=max(T[p].set[1],T[p].set[0]+v);
    else T[p].add[1]=max(T[p].add[1],T[p].add[0]+v);
}
inline void his_set(int p,int v){T[p].set[1]=max(T[p].set[1],v),T[p].his=max(T[p].his,v);}
inline void pushdown(int p){
    if(T[p].add[1])his_add(lc,T[p].add[1]),his_add(rc,T[p].add[1]),T[p].add[1]=0;
    if(T[p].set[1]!=-inf)his_set(lc,T[p].set[1]),his_set(rc,T[p].set[1]),T[p].set[1]=-inf;
    if(T[p].add[0])pushadd(lc,T[p].add[0]),pushadd(rc,T[p].add[0]),T[p].add[0]=0;
    if(T[p].set[0]!=-inf)pushset(lc,T[p].set[0]),pushset(rc,T[p].set[0]),T[p].set[0]=-inf;
}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r,T[p].set[0]=T[p].set[1]=-inf,T[p].add[0]=T[p].add[1]=0;
    if(l==r){T[p].his=T[p].mx=a[l];return;}
    build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,int v){
    if(ql>T[p].r||qr<T[p].l)return;
    if(ql<=T[p].l&&T[p].r<=qr)return pushadd(p,v);
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v);
    else if(ql>mid)update(rc,ql,qr,v);
    else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
    pushup(p);
}
inline void modify(int p,int ql,int qr,int v){
    if(ql>T[p].r||qr<T[p].l)return;
    if(ql<=T[p].l&&T[p].r<=qr)return pushset(p,v);
    pushdown(p);
    if(qr<=mid)modify(lc,ql,qr,v);
    else if(ql>mid)modify(rc,ql,qr,v);
    else modify(lc,ql,mid,v),modify(rc,mid+1,qr,v);
    pushup(p);
}
inline int query(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return -inf;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].mx;
    pushdown(p);
    if(qr<=mid)return query(lc,ql,qr);
    if(ql>mid)return query(rc,ql,qr);
    return max(query(lc,ql,mid),query(rc,mid+1,qr));
}
inline int query_his(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return -inf;
    if(ql<=T[p].l&&T[p].r<=qr)return T[p].his;
    pushdown(p);
    if(qr<=mid)return query_his(lc,ql,qr);
    if(ql>mid)return query_his(rc,ql,qr);
    return max(query_his(lc,ql,mid),query_his(rc,mid+1,qr));
}
int main(){
    n=read();
    for(int i=1;i<=n;++i)a[i]=read();
    build(1,1,n);
    q=read();
    while(q--){
        char s[20];
        scanf("%s",s);
        int l=read(),r=read();
        switch(s[0]){
            case 'Q':{write(query(1,l,r)),puts("");break;}
            case 'A':{write(query_his(1,l,r)),puts("");break;}
            case 'P':{int v=read();update(1,l,r,v);break;}
            default:{int v=read();modify(1,l,r,v);break;}
        }
    }
    return 0;
}

2018.07.27 bzoj3064: Tyvj 1518 CPU监控(线段树)的更多相关文章

  1. BZOJ3064 Tyvj 1518 CPU监控 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3064 题意概括 一个序列,要你支持以下操作: 1. 区间询问最大值 2. 区间询问历史最大值 3. ...

  2. 【bzoj3064】Tyvj 1518 CPU监控 线段树维护历史最值

    题目描述 给你一个序列,支持4种操作:1.查询区间最大值:2.查询区间历史最大值:3.区间加:4.区间赋值. 输入 第一行一个正整数T,表示Bob需要监视CPU的总时间. 然后第二行给出T个数表示在你 ...

  3. bzoj3064 Tyvj 1518 CPU监控

    Description Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看视频之外,还会做 ...

  4. [补档][Tyvj 1518]CPU监控

    [Tyvj 1518]CPU监控 题目 Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看 ...

  5. Tyvj 1518 CPU监控(线段树)

    题目描述: Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看视频之外,还会做出去玩玩和用 ...

  6. CPU监控 线段树裸题

    LINK:bzoj3064 此题甚好码了20min停下来思考的时候才发现不对的地方有点坑... 还真不好写来着 可这的确是线段树的裸题...我觉得我写应该没有什么大问题 不过思路非常的紊乱 如果是自己 ...

  7. 3064: Tyvj 1518 CPU监控

    注意这题要维护历史最大加和历史最大覆盖 /************************************************************** Problem: 3064 Us ...

  8. Tyvj 1518 CPU监控——极恶线段树

    题目大意: 给定一个区间及其各个元素的初值,要求支持如下操作: 1.区间加 2.区间赋值 3.查询区间最大值 4.查询区间历史最大值 分析: 容易想到线段树,但是细思恶极(仔细想想恶心到了极点)的是, ...

  9. bzoj 3064: Tyvj 1518 CPU监控

    Description 1.区间加 \(z\) 2.区间覆盖为 \(z\) 3.查询区间最大值 4.查询区间历史最大值 Solution 线段树维护历史最值,思想大致是维护标记出现过的最大值 考虑这种 ...

随机推荐

  1. PHP闭包

    # 提到闭包就不得不想起匿名函数,也叫闭包函数(closures),貌似PHP闭包实现主要就是靠它.声明一个匿名函数是这样: $func = function() {       }; //带结束符 ...

  2. RabbitMQ 端口号解析

    转自:https://www.cnblogs.com/liuxingke/articles/9889517.html 端口号解析 12345 - 4369 (epmd), 25672 (Erlang ...

  3. JPA和Hibernate到底是什么关系???

    转自:https://www.cnblogs.com/mosoner/p/9494250.html 在学习框架的过程中,发现学的东西很多,但是感觉他们之间的联系区别都不是很了解,知道JPA可以去实现持 ...

  4. mysql:rand()产生随机整数,CONCAT拼接时间字符串

    用存储过程插入测试数据,如果不想update_time都一样,可以进行随机字符串拼接:2月随机1天,小时随机 CONCAT('2017-02-',FLOOR(1 + (RAND() * 28)),' ...

  5. LInux下LD_LIBRARY_PATH的作用与设置

    LD_LIBRARY_PATH环境变量主要是用于指定动态链接器(Id)超早elf可执行文件运行时所依赖的动态库(so)的路径,其内容是以冒号分隔的路径列表. Id链接器优先在该变量设置的路径中查找,若 ...

  6. idea常用设置(持续更新)

    1.注释模板 Setting里找到live Templates (1)创建一个Templates Group (2)在Templates Group下创建Live Template 2.常用内置模板 ...

  7. Oracle创建表语句(Create table)语法详解及示例

    创建表(Create table)语法详解1. ORACLE常用的字段类型ORACLE常用的字段类型有VARCHAR2 (size) 可变长度的字符串, 必须规定长度CHAR(size) 固定长度的字 ...

  8. Why We Worry and What to Do About It

    Note: My new book Atomic Habits is available to preorder now. Click here to learn more. The Evolutio ...

  9. jQuery中的几个模块总结

    Query插件,以备并希望在前端方面有所长进.请批评指正. 一,类型判断全解 JQuery判断类型扩展方法:$.type() /*type: function( obj ) { if ( obj == ...

  10. Java web struct入门基础知识

    1.Struts2的前身是Opensymphony的Webwork2,实际上Strut和Webwork2合并后形成Struts2.   2.一个HelloWord示例 1)创建Web应用,所需要的Ja ...