分析

segment tree beats!模板题。

看了gxz的博客突然发现自己写的mxbtmnbt两个标记没用诶。

代码

#include <bits/stdc++.h>
#define rin(i,a,b) for(register int i=(a);i<=(b);++i)
#define irin(i,a,b) for(register int i=(a);i>=(b);--i)
#define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
typedef long long LL;
using std::cin;
using std::cout;
using std::endl; inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return x*f;
} const int MAXN=5e5+5; int n,m,a[MAXN];
int maxn[MAXN<<2],minn[MAXN<<2],
mxcnt[MAXN<<2],mncnt[MAXN<<2],
mxsec[MAXN<<2],mnsec[MAXN<<2],
tag[MAXN<<2],
ql,qr,kk;
LL sum[MAXN<<2];
bool mxbt[MAXN<<2],mnbt[MAXN<<2]; #define mid ((l+r)>>1)
#define lc (o<<1)
#define rc ((o<<1)|1) inline void pushup(int o){
sum[o]=sum[lc]+sum[rc];
if(maxn[lc]>maxn[rc]){
maxn[o]=maxn[lc];
mxcnt[o]=mxcnt[lc];
mxsec[o]=std::max(mxsec[lc],maxn[rc]);
}
else if(maxn[lc]<maxn[rc]){
maxn[o]=maxn[rc];
mxcnt[o]=mxcnt[rc];
mxsec[o]=std::max(mxsec[rc],maxn[lc]);
}
else{
maxn[o]=maxn[lc];
mxcnt[o]=mxcnt[lc]+mxcnt[rc];
mxsec[o]=std::max(mxsec[lc],mxsec[rc]);
}
if(minn[lc]<minn[rc]){
minn[o]=minn[lc];
mncnt[o]=mncnt[lc];
mnsec[o]=std::min(mnsec[lc],minn[rc]);
}
else if(minn[lc]>minn[rc]){
minn[o]=minn[rc];
mncnt[o]=mncnt[rc];
mnsec[o]=std::min(mnsec[rc],minn[lc]);
}
else{
minn[o]=minn[lc];
mncnt[o]=mncnt[lc]+mncnt[rc];
mnsec[o]=std::min(mnsec[lc],mnsec[rc]);
}
} inline void pushtag(int o,int l,int r,int _kk){
sum[o]+=1ll*_kk*(r-l+1);
maxn[o]+=_kk;
minn[o]+=_kk;
mxsec[o]+=_kk;
mnsec[o]+=_kk;
tag[o]+=_kk;
} inline void pushmaxbeat(int o,int _kk){
if(minn[o]>=_kk) return;
else if(minn[o]<_kk){
sum[o]+=1ll*(_kk-minn[o])*mncnt[o];
if(maxn[o]==minn[o]) maxn[o]=_kk;
else if(mxsec[o]==minn[o]) mxsec[o]=_kk;
minn[o]=_kk,mxbt[o]=true;
}
} inline void pushminbeat(int o,int _kk){
if(maxn[o]<=_kk) return;
else if(maxn[o]>_kk){
sum[o]+=1ll*(_kk-maxn[o])*mxcnt[o];
if(minn[o]==maxn[o]) minn[o]=_kk;
else if(mnsec[o]==maxn[o]) mnsec[o]=_kk;
maxn[o]=_kk,mnbt[o]=true;
}
} inline void pushdown(int o,int l,int r){
if(mxbt[o]){
pushmaxbeat(lc,minn[o]-tag[o]);
pushmaxbeat(rc,minn[o]-tag[o]);
mxbt[o]=false;
}
if(mnbt[o]){
pushminbeat(lc,maxn[o]-tag[o]);
pushminbeat(rc,maxn[o]-tag[o]);
mnbt[o]=false;
}
if(tag[o]){
pushtag(lc,l,mid,tag[o]);
pushtag(rc,mid+1,r,tag[o]);
tag[o]=0;
}
} void build(int o,int l,int r){
if(l==r){
maxn[o]=minn[o]=sum[o]=a[l];
mxcnt[o]=mncnt[o]=1;
mxsec[o]=-1e9,mnsec[o]=1e9;
return;
}
build(lc,l,mid);
build(rc,mid+1,r);
pushup(o);
} void add(int o,int l,int r){
if(ql<=l&&r<=qr){
pushtag(o,l,r,kk);
return;
}
pushdown(o,l,r);
if(mid>=ql) add(lc,l,mid);
if(mid<qr) add(rc,mid+1,r);
pushup(o);
} void checkmax(int o,int l,int r){
if(ql<=l&&r<=qr){
if(kk<=minn[o]) return;
else if(minn[o]<kk&&kk<mnsec[o]){
sum[o]+=1ll*(kk-minn[o])*mncnt[o];
if(maxn[o]==minn[o]) maxn[o]=kk;
else if(mxsec[o]==minn[o]) mxsec[o]=kk;
minn[o]=kk,mxbt[o]=true;
return;
}
}
pushdown(o,l,r);
if(mid>=ql) checkmax(lc,l,mid);
if(mid<qr) checkmax(rc,mid+1,r);
pushup(o);
} void checkmin(int o,int l,int r){
if(ql<=l&&r<=qr){
if(kk>=maxn[o]) return;
else if(maxn[o]>kk&&kk>mxsec[o]){
sum[o]+=1ll*(kk-maxn[o])*mxcnt[o];
if(minn[o]==maxn[o]) minn[o]=kk;
else if(mnsec[o]==maxn[o]) mnsec[o]=kk;
maxn[o]=kk,mnbt[o]=true;
return;
}
}
pushdown(o,l,r);
if(mid>=ql) checkmin(lc,l,mid);
if(mid<qr) checkmin(rc,mid+1,r);
pushup(o);
} LL querysum(int o,int l,int r){
if(ql<=l&&r<=qr) return sum[o];
pushdown(o,l,r);
LL ret=0;
if(mid>=ql) ret+=querysum(lc,l,mid);
if(mid<qr) ret+=querysum(rc,mid+1,r);
return ret;
} int querymax(int o,int l,int r){
if(ql<=l&&r<=qr) return maxn[o];
pushdown(o,l,r);
int ret=-1e9;
if(mid>=ql) ret=std::max(ret,querymax(lc,l,mid));
if(mid<qr) ret=std::max(ret,querymax(rc,mid+1,r));
return ret;
} int querymin(int o,int l,int r){
if(ql<=l&&r<=qr) return minn[o];
pushdown(o,l,r);
int ret=1e9;
if(mid>=ql) ret=std::min(ret,querymin(lc,l,mid));
if(mid<qr) ret=std::min(ret,querymin(rc,mid+1,r));
return ret;
} #undef mid
#undef lc
#undef rc int main(){
n=read();
rin(i,1,n) a[i]=read();
build(1,1,n);
m=read();
while(m--){
int opt=read(),l=read(),r=read();
if(opt==1){
int x=read();
ql=l,qr=r,kk=x;
add(1,1,n);
}
else if(opt==2){
int x=read();
ql=l,qr=r,kk=x;
checkmax(1,1,n);
}
else if(opt==3){
int x=read();
ql=l,qr=r,kk=x;
checkmin(1,1,n);
}
else if(opt==4){
ql=l,qr=r;
printf("%lld\n",querysum(1,1,n));
}
else if(opt==5){
ql=l,qr=r;
printf("%d\n",querymax(1,1,n));
}
else{
ql=l,qr=r;
printf("%d\n",querymin(1,1,n));
}
}
return 0;
}

[BZOJ4695]最假女选手:segment tree beats!的更多相关文章

  1. bzoj4695 最假女选手

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4695 [题解] SegmentTree beats!(见jiry_2论文/营员交流) 考虑只 ...

  2. BZOJ4695 最假女选手(势能线段树)

    BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...

  3. 2018.07.27 bzoj4695: 最假女选手(线段树)

    传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...

  4. bzoj4695 最假女选手(势能线段树/吉司机线段树)题解

    题意: 已知\(n\)个数字,进行以下操作: \(1.\)给一个区间\([L,R]\) 加上一个数\(x\) \(2.\)把一个区间\([L,R]\) 里小于\(x\) 的数变成\(x\) \(3.\ ...

  5. [学习笔记]Segment Tree Beats!九老师线段树

    对于这样一类问题: 区间取min,区间求和. N<=100000 要求O(nlogn)级别的算法 直观体会一下,区间取min,还要维护区间和 增加的长度很不好求.... 然鹅, 从前有一个来自杭 ...

  6. BZOJ.4695.最假女选手(线段树 Segment tree Beats!)

    题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...

  7. 【bzoj4695】最假女选手 线段树区间最值操作

    题目描述 给定一个长度为 N 序列,编号从 1 到 N .要求支持下面几种操作:1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于 ...

  8. (WC2016模拟十一)【BZOJ4695】最假女选手

    ps:好久没更博啦……这几天连着有模拟赛,等初赛前后休息的时候来疯狂补坑吧……顺便补一下前面的数论啥的? 题解: mdzz我场上写了个15分暴力长度跟标算差不多... 线段树大法好啊!这题听说很多人做 ...

  9. Segment Tree Beats 区间最值问题

    Segment Tree Beats 区间最值问题 线段树一类特殊技巧! 引出:CF671C Ultimate Weirdness of an Array 其实是考试题,改题的时候并不会区间取最值,区 ...

随机推荐

  1. 【2019CSP-S游记】咕了好久了撒

    对,证书已经发下来了,我才想起来写游记(虽然我个蒟蒻明明就是在写反思) 终于和父母商议好了以后怎么办,顺带找了一下班主任,在机房的电脑敲出来的(我来找教练,然后完全没找着,淦) 79分,众所周知CCF ...

  2. Python 入门之 软件开发规范

    Python 入门之 软件开发规范 1.软件开发规范 -- 分文件 (1)为什么使用软件开发规范: 当几百行--大几万行代码存在于一个py文件中时存在的问题: 不便于管理 修改 可读性差 加载速度慢 ...

  3. Fire Net HDU - 1045 (二分图匹配)

    题意: 给出一张图,图中'X'表示wall,'.'表示空地,可以放置blockhouse同一条直线上只能有一个blockhouse,除非有wall 隔开,问在给出的图中最多能放置多少个blockhou ...

  4. 安装ELK平台 7.3.0版本

    0. 事前准备工作 0.1 防火墙 若是使用公网IP的话可以考虑关闭防火墙,或者放行相应端口 使用内网IP的话可以不用管防火墙 0.2 关闭SElinux # setenforce 0 文件:/etc ...

  5. 图数据库:AgensGraph

    文章目录 AgensGraph简介 官网及下载 安装AgensGraph 上传并解压 添加agens用户 配置.bashrc 初始化并启动 初始化数据库 启动数据库 执行交互式终端 图数据库基础概念 ...

  6. java实现spark常用算子之countbykey

    import org.apache.spark.SparkConf;import org.apache.spark.api.java.JavaPairRDD;import org.apache.spa ...

  7. JavaSE基础:集合类

    JavaSE基础:集合类 简单认识类集 我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我们就必须把这多个对象进行存储. 而要向存储多个对象,就不能是 ...

  8. apache的rewrite机制

    当我们使用thinkphp的时候,比如说我们访问一个Test控制器的test方法,http://localhost/index.php/Test/test/1.html,那个这个1是用get方式传递的 ...

  9. python之kafka消费

    使用python3第三方工具,实现kafka消费 # -*- coding: utf-8 -*- import uuid import json from kafka import KafkaCons ...

  10. linux新建用户并分配sudo权限

    新建用户 useradd [username] 给用户设置密码 passwd [username] 设置sudo权限 首先将sudoers权限设置可写入 chmod u+w /etc/sudoers ...