[bzoj3064][线段树]Tyvj 1518 CPU监控

3064: Tyvj 1518 CPU监控

Time Limit: 20 Sec Memory Limit: 256 MB
Submit: 1401 Solved: 548
[Submit][Status][Discuss]
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

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

Sample Input

10

-62 -83 -9 -70 79 -78 -31 40 -18 -5

20

A 2 7

A 4 4

Q 4 4

P 2 2 -74

P 7 9 -71

P 7 10 -8

A 10 10

A 5 9

C 1 8 10

Q 6 6

Q 8 10

A 1 7

P 9 9 96

A 5 5

P 8 10 -53

P 6 6 5

A 10 10

A 4 4

Q 1 5

P 4 9 -69

Sample Output

79

-70

-70

-5

79

10

10

79

79

-5

10

10

HINT

数据分布如下:

第1、2个数据保证T和E均小于等于1000

第3、4个数据保证只有Q类询问

第5、6个数据保证只有C类事件

第7、8个数据保证只有P类事件

全部数据保证T和E均小于等于100000

Source

sol:

这题可以说是有点蛋疼了
先是写了个简单线段树,后来发现简单的lazy tag会丢失历史信息。
思考这么一个问题。我们当前时刻的标记正常打,然后额外记录一个add,cov的标记,add表示从上一个下放标记的时候到现在最大的add标记的值,那么这个值下放后可以和下面的值相加得到cov之前的最大值。容易发现这个标记是很容易合并的,更新儿子的时候,add[lc]=max(add[k]+nowadd[k])。第二个阶段,如果一个节点被打上了历史的cover标记的话, 因为我们的add实际上是为了给子节点中的以前的值提供更新,但是如果一个节点被打上了cov标记,那么在这个节点上面打加法标记的时候,就不能加在add上了,因为实际上子节点的值已经变了,所以直接打在cov上面。

这题写了2遍都没过,第3遍去网上抄了份代码,无耻的发了上来

#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#define his hs[k]
#define my now[k]
#define ls k<<1
#define rs k<<1|1
using namespace std;
const int N=410000;
const int inf=1e9;
int n,m;
inline int read()
{
    char c;
    int res,flag=0;
    while((c=getchar())>'9'||c<'0') if(c=='-')flag=1;
    res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=(res<<3)+(res<<1)+c-'0';
    return flag?-res:res;
}
struct Segment_Tree
{
    int x,cover,add;
}now[N<<2],hs[N<<2];
inline void simplex(int &x,int y){x=max(x,y);}
inline void h_add(int k,int v)
{
    simplex(his.x,my.x+v);
    if(my.cover>-inf)simplex(his.cover,my.cover+v);
    else simplex(his.add,my.add+v);
}

inline void h_cover(int k,int v)
{
    simplex(his.x,v);
    simplex(his.cover,v);
}

inline void m_add(int k,int v)
{
    simplex(his.x,my.x+=v);
    if(my.cover>-inf)simplex(his.cover,my.cover+=v);
    else simplex(his.add,my.add+=v);
}

inline void m_cover(int k,int v)
{
    simplex(his.x,my.x=v);
    simplex(his.cover,my.cover=v);
    my.add=0;
}

inline void pushdown(int k)
{
    if(his.add)
    {
        h_add(ls,his.add);
        h_add(rs,his.add);
        his.add=0;
    }
    if(his.cover>-inf)
    {
        h_cover(ls,his.cover);
        h_cover(rs,his.cover);
        his.cover=-inf;
    }
    if(my.add)
    {
        m_add(ls,my.add);
        m_add(rs,my.add);
        my.add=0;
    }
    if(my.cover>-inf)
    {
        m_cover(ls,my.cover);
        m_cover(rs,my.cover);
        my.cover=-inf;
    }
}

inline void pushup(int k)
{
    my.x=max(now[ls].x,now[rs].x);
    simplex(his.x,max(hs[ls].x,hs[rs].x));
}
void build(int k,int l,int r)
{
    my.cover=his.cover=-inf;
    if(l==r)
    {
        scanf("%d",&my.x),his.x=my.x;
        return ;
    }
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    his.x=-inf,pushup(k);
}
void add(int k,int L,int R,int l,int r,int x)
{
    if(l<=L&&R<=r){m_add(k,x);return ;}
    pushdown(k);
    int mid=L+R>>1;
    if(l<=mid)add(ls,L,mid,l,r,x);
    if(r>mid)add(rs,mid+1,R,l,r,x);
    pushup(k);
}
void cover(int k,int L,int R,int l,int r,int x)
{
    if(l<=L&&R<=r){m_cover(k,x);return ;}
    pushdown(k);
    int mid=L+R>>1;
    if(l<=mid)cover(ls,L,mid,l,r,x);
    if(r>mid)cover(rs,mid+1,R,l,r,x);
    pushup(k);
}
int query(int k,int L,int R,int l,int r)
{
    if(l<=L&&R<=r)return my.x;
    pushdown(k);
    int mid=L+R>>1,ans=-inf;
    if(l<=mid)ans=max(ans,query(ls,L,mid,l,r));
    if(r>mid)ans=max(ans,query(rs,mid+1,R,l,r));
    return ans;
}
int ask(int k,int L,int R,int l,int r)
{
    if(l<=L&&R<=r)return his.x;
    pushdown(k);
    int mid=L+R>>1,ans=-inf;
    if(l<=mid)ans=max(ans,ask(ls,L,mid,l,r));
    if(r>mid)ans=max(ans,ask(rs,mid+1,R,l,r));
    return ans;
}
int main()
{
//  freopen("3064.in","r",stdin);
//  freopen("3064h.out","w",stdout);
    char opt[5];
    scanf("%d",&n);
    build(1,1,n);
    m=read();
    int a,b,c;
    while(m--)
    {
        scanf("%s",opt);
        a=read();
        b=read();
        if(opt[0]=='Q') printf("%d\n",query(1,1,n,a,b));
        if(opt[0]=='A') printf("%d\n",ask(1,1,n,a,b));
        if(opt[0]=='P')
        {
            scanf("%d",&c);
            add(1,1,n,a,b,c);
        }
        if(opt[0]=='C')
        {
            scanf("%d",&c);
            cover(1,1,n,a,b,c);
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值