zoukankan      html  css  js  c++  java
  • P4314 CPU监控

    线段树标记好题

    这题要支持区间加,区间赋值,区间查最大值,区间查历史最大值。

    直接用线段树维护区间最大值和历史最大值,再打俩 (tag) 是不够的,因为(tag) 不一定能够及时下传至叶子节点

    因此我们需要额外多打俩 (tag):(从上次更新以后)加法标记的历史最大值,(从上次更新以后)赋值标记的历史最大值。并且我们保证赋值操作绝对优于加法操作,即原有加法标记,再赋值以后会取消加法标记(但是不会清空加法标记的历史最大值);原有历史标记,再加法就直接视为赋值为某个值的操作。

    因此,我们在操作标记的时候要对有赋值标记的情况进行特殊处理。

    需要注意的是,下放标记的时候,我们需要先下放加法标记,再下放赋值标记,因为加法标记的历史最大值记录的是上次更新之后到第一次赋值标记之前的所有加法的最大值,我们将用 (now~max + history~add~tag) 来更新 (history~max),而这个 (now~max) 应该是上一次更新之后的 (now~max),如果先用赋值标记更新的话,(now~max) 信息就会出错。

    赋值标记不需要管 (now~max) 是否正确,因为用不到。

    关键代码:

    //vst : 是否存在赋值标记
    inline void push_set(int cur, int v, int hv) {
    	if (!cur)	return ;
    	mx[cur] = v, MAX(hmx[cur], hv);
    	if (vst[cur])
    		MAX(hstag[cur], hv), stag[cur] = v;//Attention!!
    	else	vst[cur] = true, stag[cur] = v, hstag[cur] = hv;
    	atag[cur] = 0;
    }
    inline void push_add(int cur, int v, int hv) {
    	if (!cur)	return ;
    	MAX(hmx[cur], mx[cur] + hv), mx[cur] += v;//Attention!!!  <-error
    	if (vst[cur])	push_set(cur, stag[cur] + v, stag[cur] + hv);
    	else	MAX(hatag[cur], atag[cur] + hv), atag[cur] += v;
    }
    inline void pushdown(int cur) {
    	if (vst[cur] && atag[cur])	exit(-1);
    	push_add(ls[cur], atag[cur], hatag[cur]),
    	push_add(rs[cur], atag[cur], hatag[cur]),
    	atag[cur] = hatag[cur] = 0;
    	if (vst[cur]) {
    		push_set(ls[cur], stag[cur], hstag[cur]),
    		push_set(rs[cur], stag[cur], hstag[cur]),
    		stag[cur] = hstag[cur] = 0;
    		vst[cur] = 0;
    	}
    }
    
  • 相关阅读:
    设计模式
    Linux 使用 script 分享
    动态代理中的 UndeclaredThrowableException 以及其他异常
    浅析 Spring 异常处理
    SLAM中的优化理论(二)- 非线性最小二乘
    SLAM中的优化理论(一)—— 线性最小二乘
    卡尔曼滤波器推导与解析
    Python学习(一) —— matplotlib绘制三维轨迹图
    ZED 相机 && ORB-SLAM2安装环境配置与ROS下的调试
    [转载]如何使用USSD命令设置呼叫转移
  • 原文地址:https://www.cnblogs.com/JiaZP/p/13387339.html
Copyright © 2011-2022 走看看