[bzoj3064] [Tyvj 1518] CPU监控

Posted hbyer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[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

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

Solution

论文题就是强大QAQ

考虑把区间覆盖转化成区间取(max),标记记成二元组((x,y)),表示先区间加上(x),再对(y)(max),也就是(a_i=max(a_i+x,y))

那么区间加标记就是((x,-infty)),区间覆盖就是((-infty,x))

然后对于每个点记两个标记(now)(history),表示当前标记和历史最大标记。

那么对于当前标记,将((c,d))((a,b))上合并,显然结果是((a+c,max(b+c,d)))

对于历史最大标记,标记((a,b))可以看成是一个形如(y=max(x+a,b))的函数,显然这是个分段函数,第一段是(y=b),第二段是(y=x+a),两个标记合并对于每个(x)都是要取最大值,所以取函数最上面那一段,标记((a,b))((c,d))合并的结果就是((max(a,c),max(b,d)))

然后具体看代码吧,(我能说我因为fread挂了而T了一版吗QAQ)

#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;

namespace fast_IO {
    template <typename T> inline void read(T &x) {
        x=0;T f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
    template <typename T,typename... Args> inline void read(T& x,Args& ...args) {
        read(x),read(args...);
    }

    char buf2[1<<21],a[80];int p,p3=-1;

    inline void flush() {fwrite(buf2,1,p3+1,stdout),p3=-1;}
    template <typename T> inline void write(T x) {
        if(p3>(1<<20)) flush();
        if(x<0) buf2[++p3]='-',x=-x;
        do {a[++p]=x%10+48;} while(x/=10);
        do {buf2[++p3]=a[p];} while(--p);
        buf2[++p3]='
';
    }
    template <typename T,typename... Args> inline void write(T x,Args ...args) {
        write(x),write(args...);
    }
}

using fast_IO :: read;
using fast_IO :: write;
using fast_IO :: flush;

const int maxn = 1e5+10;
const int inf = 0x3f3f3f3f;

int n,m,val[maxn];
char s[10];

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct Segment_Tree {
    int hmax[maxn<<2],nmax[maxn<<2];
    struct tag {
        int add,mx;
        inline void init() {add=0,mx=-inf;}
        inline tag operator + (const tag &rhs) const {return (tag){max(-inf,add+rhs.add),max(mx+rhs.add,rhs.mx)};}
        inline tag operator * (const tag &rhs) const {return (tag){max(add,rhs.add),max(mx,rhs.mx)};}
    }nlazy[maxn<<2],hlazy[maxn<<2];
    inline void update(int p) {
        hmax[p]=max(hmax[ls],hmax[rs]);
        nmax[p]=max(nmax[ls],nmax[rs]);
    }
    inline void push_tag(int p,tag now,tag history) {
        hlazy[p]=hlazy[p]*(nlazy[p]+history);
        nlazy[p]=nlazy[p]+now;
        hmax[p]=max(hmax[p],max(nmax[p]+history.add,history.mx));
        nmax[p]=max(nmax[p]+now.add,now.mx);
    }
    inline void pushdown(int p) {
        push_tag(ls,nlazy[p],hlazy[p]);
        push_tag(rs,nlazy[p],hlazy[p]);
        nlazy[p].init(),hlazy[p].init();
    }
    void modify(int p,int l,int r,int x,int y,int add,int mx) {
        if(x<=l&&r<=y) return push_tag(p,(tag){add,mx},(tag){add,mx}),void();
        pushdown(p);
        if(x<=mid) modify(ls,l,mid,x,y,add,mx);
        if(y>mid) modify(rs,mid+1,r,x,y,add,mx);
        update(p);
    }
    int query_hmax(int p,int l,int r,int x,int y) {
        if(x<=l&&r<=y) return hmax[p];
        int ans=-inf;pushdown(p);
        if(x<=mid) ans=max(ans,query_hmax(ls,l,mid,x,y));
        if(y>mid) ans=max(ans,query_hmax(rs,mid+1,r,x,y));
        return ans;     
    }
    int query_nmax(int p,int l,int r,int x,int y) {
        if(x<=l&&r<=y) return nmax[p];
        int ans=-inf;pushdown(p);
        if(x<=mid) ans=max(ans,query_nmax(ls,l,mid,x,y));
        if(y>mid) ans=max(ans,query_nmax(rs,mid+1,r,x,y));
        return ans;     
    }
    void build(int p,int l,int r) {
        hlazy[p].init(),nlazy[p].init();
        if(l==r) return hmax[p]=nmax[p]=val[l],void();
        build(ls,l,mid),build(rs,mid+1,r),update(p);
    }
}SGT;

#undef ls
#undef rs
#undef mid

int main() {
    read(n);
    for(int i=1;i<=n;i++) read(val[i]);
    SGT.build(1,1,n);
    read(m);
    for(int i=1;i<=m;i++) {
        scanf("%s",s+1);int x,y,z;read(x,y);
        if(s[1]=='Q') write(SGT.query_nmax(1,1,n,x,y));
        else if(s[1]=='A') write(SGT.query_hmax(1,1,n,x,y));
        else if(s[1]=='P') read(z),SGT.modify(1,1,n,x,y,z,-inf);
        else read(z),SGT.modify(1,1,n,x,y,-inf,z);
    }
    flush();
    return 0;
}

以上是关于[bzoj3064] [Tyvj 1518] CPU监控的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 3064: Tyvj 1518 CPU监控

[bzoj3064] [Tyvj 1518] CPU监控

bzoj3064Tyvj 1518 CPU监控 线段树维护历史最值

3064: Tyvj 1518 CPU监控

bzoj3064 CPU监控

[bzoj3064]CPU监控