CPU监控 解题报告

CPU监控

这种题就需要小黄鸭调试法,不行就重构,动态gdb可能会死人,一堆tag的...

维护历史最值的一个核心是历史最值tag,它的意义是从上一次这个点下放tag之后到当前时刻的这个点的tag达到过的最大值。

我们注意到tag的作用是按找时间限制的,所以我们可以认为历史最大tag是一个前缀最大值。

有了历史最值tag,我们就可以完成pushdown的工作辣

就把历史tag放给儿子的历史tag和历史最值,这时候更新需要用儿子的当前值结合自己的历史最大进行更新。

对这个题维护一个二元组\(tag(a,b)\),这个tag对值\(v\)就表示\(\max(v+a,b)\),区间加就是\((c,-inf)\),区间覆盖\((-inf,c)\)

考虑两个按时间顺序的tag的合并(a,b)与(c,d),那么合并以后是\((a+c,\max(b+c,d))\)

注意\(a+c\)\(-inf\)取个\(\max\),否则可能会爆掉int...

然后注意一下细节就可以了


Code:

#include <cstdio>
#include <cctype>
#include <algorithm>
using std::max;
template <class T>
void read(T &x)
{
    int f=0;x=0;char c=getchar();
    while(!isdigit(c)) f|=c=='-',c=getchar();
    while(isdigit(c)) x=x*10+c-'0',c=getchar();
    if(f) x=-x;
}
const int inf=0x3f3f3f3f;
const int N=1e5+10;
#define ls id<<1
#define rs id<<1|1
int n,m,a[N];
struct koito_yuu
{
    int a,b;
    koito_yuu(){}
    koito_yuu(int A,int B){a=A,b=B;}
    koito_yuu friend operator +(koito_yuu a,koito_yuu b){return koito_yuu(max(-inf,a.a+b.a),max(a.b+b.a,b.b));}
    int friend operator +(koito_yuu a,int b){return max(a.a+b,a.b);}
    void upt(koito_yuu v){a=max(a,v.a),b=max(b,v.b);}
}tag[N<<2],histag[N<<2];
int mx[N<<2],hismx[N<<2];
void updata(int id)
{
    mx[id]=max(mx[ls],mx[rs]);
    hismx[id]=max(hismx[ls],hismx[rs]);
}
void pushdown(int id)
{
    if(tag[id].a||tag[id].b!=-inf)
    {
        hismx[ls]=max(hismx[ls],histag[id]+mx[ls]);
        hismx[rs]=max(hismx[rs],histag[id]+mx[rs]);
        histag[ls].upt(tag[ls]+histag[id]);
        histag[rs].upt(tag[rs]+histag[id]);
        histag[id]=koito_yuu(0,-inf);

        tag[ls]=tag[ls]+tag[id];
        tag[rs]=tag[rs]+tag[id];
        mx[ls]=tag[id]+mx[ls];
        mx[rs]=tag[id]+mx[rs];
        tag[id]=koito_yuu(0,-inf);
    }
}
void build(int id,int l,int r)
{
    tag[id]=histag[id]=koito_yuu(0,-inf);
    if(l==r)
    {
        mx[id]=hismx[id]=a[l];
        return;
    }
    int mid=l+r>>1;
    build(ls,l,mid),build(rs,mid+1,r);
    updata(id);
}
int query(int id,int L,int R,int l,int r)
{
    if(l==L&&r==R) return mx[id];
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) return query(ls,L,Mid,l,r);
    else if(l>Mid) return query(rs,Mid+1,R,l,r);
    else return max(query(ls,L,Mid,l,Mid),query(rs,Mid+1,R,Mid+1,r));
}
int hisquery(int id,int L,int R,int l,int r)
{
    if(l==L&&r==R) return hismx[id];
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) return hisquery(ls,L,Mid,l,r);
    else if(l>Mid) return hisquery(rs,Mid+1,R,l,r);
    else return max(hisquery(ls,L,Mid,l,Mid),hisquery(rs,Mid+1,R,Mid+1,r));
}
void change(int id,int L,int R,int l,int r,koito_yuu d)
{
    if(l==L&&r==R)
    {
        hismx[id]=max(hismx[id],d+mx[id]);
        histag[id].upt(tag[id]+d);
        mx[id]=d+mx[id];
        tag[id]=tag[id]+d;
        return;
    }
    pushdown(id);
    int Mid=L+R>>1;
    if(r<=Mid) change(ls,L,Mid,l,r,d);
    else if(l>Mid) change(rs,Mid+1,R,l,r,d);
    else change(ls,L,Mid,l,Mid,d),change(rs,Mid+1,R,Mid+1,r,d);
    updata(id);
}
int main()
{
    read(n);
    for(int i=1;i<=n;i++) read(a[i]);
    build(1,1,n);
    read(m);
    char op[4];
    for(int l,r,x,i=1;i<=m;i++)
    {
        scanf("%s",op);
        read(l),read(r);
        if(op[0]=='Q') printf("%d\n",query(1,1,n,l,r));
        else if(op[0]=='A') printf("%d\n",hisquery(1,1,n,l,r));
        else if(op[0]=='P')
        {
            read(x);
            change(1,1,n,l,r,koito_yuu(x,-inf));
        }
        else
        {
            read(x);
            change(1,1,n,l,r,koito_yuu(-inf,x));
        }
    }
    return 0;
}

2019.3.21

转载于:https://www.cnblogs.com/butterflydew/p/10574650.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值