zoukankan      html  css  js  c++  java
  • BZOJ3064: Tyvj 1518 CPU监控

    3064: Tyvj 1518 CPU监控

    Time Limit: 20 Sec Memory Limit: 256 MB
    Submit: 1391 Solved: 545
    [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

    题解

    史上超恶心线段树神题。

    一般神题的题解网上大多题解都是fangpi
    所以大家快来看我fangpi

    理一理思路。

    不考虑查询历史,只需一个值,两个标记
    (ma):区间最大
    (add):区间加
    (fill):区间赋值

    如果一个区间有(fill)标记,那么所有的(add)直接(add)(fill)上即可

    怎么做历史呢?
    如果只记录历史最大的话

    可能有一个区间一直接受(add)标记下放,而没有下传,最终(add)不如中间某个(add)
    所以加一个标记(his\_add),表示下传标记前的最大(add)

    可能有一个区间一直接受(fill)(add)(add)加到(fill)里),没有下传,导致最终(fill)不如中间某个(fill)
    所以加一个标记(his\_fill),表示下传标记前的最大(fill)

    没有覆盖用(-INF)表示,为什么不用INF?因为在代码里有一个地方用-INF可以方便取max,避免分类讨论

    下面分析标记的下传

    四个标记,(fill),(add),(his\_add),(his\_fill)

    先下传(fill)?。。那你记录(his\_add)有个卵用
    先下传(add)?。。那你记录(his\_add)有个卵用
    先下传(his\_fill)?。。没毛病传吧
    传给(son)(his\_fill)
    没了

    然后传(his\_add)
    更新(his\_ma[son] = max(his\_ma[son], ma[son] + his\_add[now]))
    更新(his\_fill[son] = max(his\_fill[son], fill[son] + his\_add[now]))
    更新(his\_add[son] = max(his\_add[son], add[son] + his\_add[now]))
    还能更新啥?
    啥也不能更新了,你记的是上次下传到现在的历史最大(add)值,当然只能更新历史
    注意如果(son)没有(fill)不能更新(his\_fil)(his\_fill)此时应该是(-INF),不存在)
    如果(son)(fill)不能更新(his\_add)(因为所有(add)都加(fill)里了,历史最大值记录到(his\_fill)里了,没有(his\_add)(add)什么事了)

    考虑(add)(fill)共存时,先传(add)还是先传(fill)(不共存当然先传有的那个了(废话))

    如果(add)(fill)共存,不可能先有(fill),否则(and)应该被加到(fill)
    也不可能先有(add),因为(fill)会把(add)盖掉

    所以不可能共存
    i传一个就行了

    然后完了。
    (顺便膜一发zcy%%%%%%%%%%)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <algorithm>
    #include <map>
    #include <cmath>
    inline long long max(long long a, long long b){return a > b ? a : b;}
    inline long long min(long long a, long long b){return a < b ? a : b;}
    inline void swap(long long &x, long long &y){long long tmp = x;x = y;y = tmp;}
    inline void read(long long &x)
    {
        x = 0;char ch = getchar(), c = ch;
        while(ch < '0' || ch > '9') c = ch, ch = getchar();
        while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
        if(c == '-') x = -x;
    }
    const long long INF = 0x3f3f3f3f3f3f3f3f;
    const long long MAXN = 500000 + 10;
    struct Node
    {
    	long long ma, add, fill;
    	long long his_ma, his_add, his_fill;
    	long long l,r; 
    	Node(){add = his_add = 0;fill = his_fill =  ma = his_ma = -INF;}
    }node[MAXN << 2];
    void pushup(long long o)
    {
    	node[o].ma = max(node[o << 1].ma, node[o << 1 | 1].ma);
    	node[o].his_ma = max(node[o << 1].his_ma, node[o << 1 | 1].his_ma);
    }
    
    void pushdown(long long o)
    {
    
    	for(int i = 0;i < 2;++ i)
    	{
    		int son = o << 1 | i;
    /*
    	ma:当前最大
    	add:未被覆盖时,当前加法标记。有覆盖标记时,add全部加到覆盖标记里
    	fill:当前覆盖标记
    	
    	his_ma:历史最大值
    	his_fill:从 上一次下放标记到现在,历史最大覆盖标记 
    	his_add:从 上一次下下放标记到现在,历史add标记最大值
    */
    		//先下传his_add标记 
    		node[son].his_ma = max(node[son].his_ma, max(node[o].his_fill, node[son].ma + node[o].his_add));
    		if(node[son].fill == -INF) node[son].his_add = max(node[son].his_add, node[son].add + node[o].his_add);
    		else node[son].his_fill = max(node[son].his_fill, node[son].fill + node[o].his_add);
    		
    		//下传fill标记  没有才下传add标记 
    		
    		if(node[o].fill != -INF)
    		{
    			node[son].ma = node[son].fill = node[o].fill;
    			node[son].add = 0;
    		}
    		else if(node[o].add)
    		{
    			if(node[son].fill == -INF) node[son].add += node[o].add;
    			else node[son].fill += node[o].add;
    			node[son].ma += node[o].add;
    		}
    		node[son].his_fill = max(node[son].his_fill, max(node[son].fill, node[o].his_fill));
    		node[son].his_add = max(node[son].his_add, node[son].add);
    	}
    	node[o].add = node[o].his_add = 0;
    	node[o].fill = node[o].his_fill = -INF;
    }
    long long n, num[MAXN], q;
    void build(long long o = 1, long long l = 1, long long r = n)
    {
    	node[o].l = l, node[o].r = r;
    	if(l == r)
    	{
    		node[o].ma = node[o].his_ma = num[l];
    		return;
    	}
    	long long mid = (l + r) >> 1;
    	build(o << 1, l, mid);
    	build(o << 1 | 1, mid + 1, r);
    	pushup(o);
    }
    void modify(long long t, long long ll, long long rr, long long k, long long o = 1, long long l = 1, long long r = n)
    {
    	if(l != r) pushdown(o);
    	if(ll <= l && rr >= r)
    	{
    		if(t) node[o].add = node[o].his_add = k, node[o].ma += k;
    		else node[o].ma = node[o].fill = node[o].his_fill = k;
    		node[o].his_ma = max(node[o].his_ma, node[o].ma);
    		return;
    	}	
    	long long mid = (l + r) >> 1;
    	if(mid >= ll) modify(t, ll, rr, k, o << 1, l, mid);
    	if(mid < rr) modify(t, ll, rr, k, o << 1 | 1, mid + 1, r);
    	pushup(o);
    }
    long long ask(long long t, long long ll, long long rr, long long o = 1, long long l = 1, long long r = n)
    {
    	if(l != r) pushdown(o);
    	if(ll <= l && rr >= r) return t ? node[o].ma : node[o].his_ma;
    	long long mid = (l + r) >> 1, a = -INF, b = -INF;
    	if(mid >= ll) a = ask(t, ll, rr, o << 1, l, mid);
    	if(mid < rr) b = ask(t, ll, rr, o << 1 | 1, mid + 1, r);
    	pushup(o);
    	return max(a, b);
    }
    char c[10];
    long long tmp1, tmp2, tmp3;
    int main()
    {
    	read(n);
    	for(long long i = 1;i <= n;++ i)
    		read(num[i]);
    	build();
    	read(q);
    	for(long long i = 1;i <= q;++ i)
    	{
    		scanf("%s", c + 1);
    		read(tmp1), read(tmp2);
    		if(c[1] == 'Q') printf("%lld
    ", ask(1, tmp1, tmp2));
    		else if(c[1] == 'A') printf("%lld
    ", ask(0, tmp1, tmp2));
    		else if(c[1] == 'P') read(tmp3), modify(1, tmp1, tmp2, tmp3);
    		else read(tmp3), modify(0, tmp1, tmp2, tmp3);
    	}
        return 0;
    }
    
  • 相关阅读:
    NFS部署
    centos6 编译安装 mysql5.6----------centos7编译安装MySQL5.7
    db2部署
    FTP服务部署
    ssh 免交互式登陆
    dockerfile
    docker 入门
    求助 webBrowser 的兼容性问题 有偿的 500红包
    EF 请求数据是缓存 求大神解释
    跪求 EF缓存问题 也不知道是不是缓存 问题
  • 原文地址:https://www.cnblogs.com/huibixiaoxing/p/8568285.html
Copyright © 2011-2022 走看看