题目大意:

给定一个区间及其各个元素的初值,要求支持如下操作:

1.区间加

2.区间赋值

3.查询区间最大值

4.查询区间历史最大值

分析:

容易想到线段树,但是细思恶极(仔细想想恶心到了极点)的是,最后查询区间历史最大值的操作。

如果只记录区间历史最大值显然不能下放,如果单纯更新区间加,区间赋值最大值,可能会出现历史最大值更新不及时的情况。如先赋值很大值,未来得及下放,又赋值很小,导致子区间历史最大值不能更新。又如如果区间加只取最大值,可能会只取最大值,导致实际上忽视了一些使区间加变小的操作。

。。。。(此处省略若千字)

所以我们记录如下几点:

1.mx(x)当前区间最大值

2.hx(x)历史区间最大值

3.ad(x)当前区间加

4.ha(x)历史最大区间加

5.ch(x)当前区间赋值

6.hc(x)历史最大区间赋值

注意 :

这里我们所谓的ha,hc是指在上一次pushdown之后,期间进行的操作中的最大值。是可以清零的,不像hx。

初值:ha=ad=0,ch=hc=-inf。

因为每次都先进行pushdown,所以ha、hc直接随着ad、ch更新。

注意的是pushdown中的许多讨论,自己分析清楚。

其实每次都pushdown是很慢的,会tle两个点。

然后就把区间内的l、r不记录了,竟然不开O2水过。

详见代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=+;
const ll inf=1e13;
int root,n,e;
ll a[N];
int cc;
struct node{
ll add,ch;
ll mx,hx;
ll had,hch;//一段时间内最值
#define ad(x) t[x].add
#define ch(x) t[x].ch
#define mx(x) t[x].mx
#define hx(x) t[x].hx
#define ha(x) t[x].had
#define hc(x) t[x].hch
#define l(x) t[x].l
#define r(x) t[x].r
}t[*N];
void pushup(int x)
{
int s1=x<<,s2=x<<|;
mx(x)=max(mx(s1),mx(s2));
hx(x)=max(hx(s1),hx(s2));
}
void build(int x,int L,int R)
{
if(L==R)
{
ad(x)=;ch(x)=-inf;ha(x)=;hc(x)=-inf;
mx(x)=hx(x)=a[L];
return;
}
int mid=(L+R)>>;
ad(x)=;ch(x)=-inf;ha(x)=;hc(x)=-inf;
mx(x)=hx(x)=-inf;
build(x<<,L,mid);
build(x<<|,mid+,R);
pushup(x);
}
void pushdown(int x)
{
for(int i=;i<=;i++)
{
int s=x<<|i;
hx(s)=max(hx(s),max(mx(s)+ha(x),hc(x)));
if(ch(s)!=-inf) hc(s)=max(hc(s),ch(s)+ha(x));
else ha(s)=max(ha(s),ad(s)+ha(x));
if(ad(x))
{
if(ch(s)!=-inf) ch(s)+=ad(x);
else ad(s)+=ad(x);
mx(s)+=ad(x);
}
if(ch(x)!=-inf)
{
mx(s)=ch(s)=ch(x);
ad(s)=;
}
hc(s)=max(hc(s),max(ch(s),hc(x)));
ha(s)=max(ha(s),ad(s));
}
hc(x)=-inf;
ad(x)=;ch(x)=-inf;ha(x)=;
}
void add(int x,int l,int r,int L,int R,ll c)
{
if(l!=r)pushdown(x);
if(L<=l&&r<=R)
{
ad(x)+=c;ha(x)+=c;
mx(x)+=c;hx(x)=max(mx(x),hx(x));
return;
} int mid=(l+r)>>;
if(L<=mid) add(x<<,l,mid,L,R,c);
if(R>mid) add(x<<|,mid+,r,L,R,c);
pushup(x);
}
void chan(int x,int l,int r,int L,int R,ll c)
{
if(l!=r)pushdown(x);
if(L<=l&&r<=R)
{
ch(x)=c,mx(x)=c;hc(x)=c;
hx(x)=max(hx(x),mx(x));
return;
}
int mid=(l+r)>>;
if(L<=mid) chan(x<<,l,mid,L,R,c);
if(R>mid) chan(x<<|,mid+,r,L,R,c);
pushup(x);
}
ll qx(int x,int l,int r,int L,int R)
{
if(l!=r)pushdown(x);
if(L<=l&&r<=R)
{
return mx(x);
}
int mid=(l+r)>>;
ll res=-inf;
if(L<=mid) res=max(res,qx(x<<,l,mid,L,R));
if(R>mid) res=max(res,qx(x<<|,mid+,r,L,R));
return res;
}
ll qh(int x,int l,int r,int L,int R)
{
if(l!=r)pushdown(x);
if(L<=l&&r<=R)
{
return hx(x);
}
int mid=(l+r)>>;
ll res=-inf;
if(L<=mid) res=max(res,qh(x<<,l,mid,L,R));
if(R>mid) res=max(res,qh(x<<|,mid+,r,L,R));
return res;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%lld",&a[i]);
root=;
build(,,n);
scanf("%d",&e);
char q;
int x,y;
ll z;
while(e)
{
cin>>q;
if(q=='Q')
{
scanf("%d%d",&x,&y);
printf("%lld\n",qx(root,,n,x,y));
}
else if(q=='A')
{ scanf("%d%d",&x,&y);
printf("%lld\n",qh(root,,n,x,y));
}
else if(q=='P')
{
scanf("%d%d%lld",&x,&y,&z);
add(root,,n,x,y,z);
}
else{
scanf("%d%d%lld",&x,&y,&z);
chan(root,,n,x,y,z);
}
e--;
}
return ;
}

做这个题要有勇于试错的精神,和坚持不懈的意志。

Tyvj 1518 CPU监控——极恶线段树的更多相关文章

  1. [补档][Tyvj 1518]CPU监控

    [Tyvj 1518]CPU监控 题目 Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看 ...

  2. 【bzoj3064】Tyvj 1518 CPU监控 线段树维护历史最值

    题目描述 给你一个序列,支持4种操作:1.查询区间最大值:2.查询区间历史最大值:3.区间加:4.区间赋值. 输入 第一行一个正整数T,表示Bob需要监视CPU的总时间. 然后第二行给出T个数表示在你 ...

  3. Tyvj 1518 CPU监控(线段树)

    题目描述: Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看视频之外,还会做出去玩玩和用 ...

  4. 2018.07.27 bzoj3064: Tyvj 1518 CPU监控(线段树)

    传送门 线段树好题. 维护区间加,区间覆盖,区间最大,区间历史最大. 这个东西在国家集训队2016论文集之<区间最值操作与历史最值问题--杭州学军中学 吉如一>中讲的已经很详细了. 简单来 ...

  5. bzoj3064 Tyvj 1518 CPU监控

    Description Bob需要一个程序来监视CPU使用率.这是一个很繁琐的过程,为了让问题更加简单,Bob会慢慢列出今天会在用计算机时做什么事. Bob会干很多事,除了跑暴力程序看视频之外,还会做 ...

  6. bzoj 3064: Tyvj 1518 CPU监控

    Description 1.区间加 \(z\) 2.区间覆盖为 \(z\) 3.查询区间最大值 4.查询区间历史最大值 Solution 线段树维护历史最值,思想大致是维护标记出现过的最大值 考虑这种 ...

  7. BZOJ3064 Tyvj 1518 CPU监控 线段树

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3064 题意概括 一个序列,要你支持以下操作: 1. 区间询问最大值 2. 区间询问历史最大值 3. ...

  8. 3064: Tyvj 1518 CPU监控

    注意这题要维护历史最大加和历史最大覆盖 /************************************************************** Problem: 3064 Us ...

  9. bzoj 3196 Tyvj 1730 二逼平衡树(线段树套名次树)

    3196: Tyvj 1730 二逼平衡树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1807  Solved: 772[Submit][Stat ...

随机推荐

  1. 使用IdentityServer4实现一个简单的Oauth2客户端模式授权

    1.首先新建一个webAPI项目做为IdentityServer的服务端,提供生成Token的服务,首先修改Startup.cs文件,如下图: 2.增加一个Config.cs文件,以便于提供资源和认证 ...

  2. QQ聊天记录备份助手 v1.0——搜索、备份、恢复QQ聊天记录文件,重装系统必备

    项目地址 https://github.com/guoyaohua/QQBackUp 开发环境 Netbean JAVA 功能描述 自动搜索硬盘中的QQ聊天记录文件 可选择的备份QQ数据记录 还原QQ ...

  3. BGFX 渲染引擎中着色器代码的调试方法

    在实时渲染的图形开发中,着色器代码(Shader)越来越复杂,于是单纯的靠经验和不断试错的开发和调试方法早已不能满足实际需求.使用调试工具进行调试,成为开发中重要的方法.Bgfx 是一款跨平台.抽象封 ...

  4. Windows10 家庭版 Docker的安装

    Docker的安装 1.简介:Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中, 然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全 ...

  5. Centos下堡垒机Jumpserver V3.0环境部署完整记录(2)-配置篇

    前面已经介绍了Jumpserver V3.0的安装,基于这篇安装文档,下面说下Jumpserver安装后的的功能使用: 一.jumpserver的启动 Jumpserver的启动和重启 [root@t ...

  6. poj1426 Find The Multiple(c语言巧解)

    Find The Multiple Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 36335   Accepted: 151 ...

  7. M2贡献分分配方案

    1.初始分每个人都为0. 2.每周分配任务,按任务计分. 3.每周每个人有12.5分. 4.次周完成本周任务计6分. 5.未全部完成本周任务计6分. 6.12月29日统计分数,多出来的分数按完成任务数 ...

  8. windows上tomcat8的安装及配置

    提示:在安装tomcat之前,确定安装好jdk. 一.下载tomcat8 http://tomcat.apache.org/download-80.cgi 点击这个网址 根据自己电脑的才做系统版本安装 ...

  9. 正则表达式(java)

    概念: 正则表达式,又称规则表达式.(英语:Regular Expression,在代码中常简写为regex.regexp或RE),计算机科学的一个概念. 正则表通常被用来检索.替换那些符合某个模式( ...

  10. 百度地图marker点击任意一个当前的变化,其余的marker不变

    百度地图marker点击任意一个当前的变化,其余的marker不变 最近做的百度地图,遇到一个问题,就是在for循环里面执行marker的点击事件 没有可以比对的对象,每次点击marker的时候,i都 ...