Segment Tree Beats 区间最值问题

线段树一类特殊技巧!

引出:CF671C Ultimate Weirdness of an Array

其实是考试题,改题的时候并不会区间取最值,区间求和,之后秉承着好好学习的态度,学习了Segment tree Beats

套路是维护出区间最小值和次小值,以及区间最小值数量。之后再维护出题目中需要的东西就好了。之后怎么处理呢,如果我们需要维护出区间和x取max,那么,如果x<=minn[rt],那么直接return;如果x<minx[rt](minx[rt]为区间次小值),那么之间将最小值改成x,之后再改需要改的信息就好了...但是,如果x>=minx[rt],那么就递归处理子树信息。

什么?你说它的时间复杂度?每次修改均摊O(nlogn)

什么时候修改是O(n)呢,就是所有点的状态大概接近于1,2,1,2,1,2,1,2,1,2...之后对3取max,这种情况下单次修改是O(n)的,但是修改完这次之后,不论下一次修改是什么,都是O(1)的,并且,求和不会超过O(nlogn)

其实本质上,什么拖累了时间复杂度呢?就是当区间中不同的元素特别多的时候,单次修改的时间复杂度会较为高昂,但是假设,我们修改了A个元素,那么就相当于区间的集合中少了A-1个元素,并且我们知道这次修改最大是Alogn的,那么下一次修改就相当于少了A-1个不同元素,也就是说,假设没有这次修改,下一次修改B个元素的话,那么有了这次修改下一次就相当于修改了B-A+1个元素,那么我们考虑将所有的修改操作的时间复杂度求和,接近于O(nlogn),但是,这并不完全,因为每次修改可能会导致某些区间的元素个数增加。那么我们考虑会增加多少呢?因为所有修改的元素都修改成了一个值,那么就相当于有些区间的元素的个数多了1。那么修改的时间复杂度就是期望上(Qlogn+nlogn),但是其实并不会跑满,而且实际效率很快。

那么线段树的题嘛,考虑加上区间修改等操作的时间复杂度。因为每次区间覆盖的话,非常棒,取消了许多节点的独立性,时间复杂度完全没有问题!但是区间加的话假如一个区间的是1,2,3,4,5,6,1,2,3,4,5,6之后针对前6个区间加6,那么相当于增加了一倍的独立点个数,但是反过来考虑,构成1,2,3,4,5,6,1,2,3,4,5,6需要这种特殊构造,而特殊构造耗费的操作数量是接近n级别的,那么其实反过来考虑一下,时间复杂度没有任何问题,因为,其实我们考虑,只有区间修改的时间复杂度,是logn,那么为什么是O(logn)的原因是因为打了lazy标记,那么其实我们假装这里打了一个lazy标记,那么其实每次修改的节点只有log级别的,那么其实A也只增加了log级别的存在,而每次PushDown增加的也只是logn*Alogn其实也就是Alognlogn的时间复杂度。这非常正确,请不要反驳我。

那么我们考虑完时间复杂度了,是不是该讲题了?

并不是,因为例题没有那么多...

那么我们先举一个例子

给定一个长度为n的数列A,接下来有m次操作:

• 区间[l,r]中的所有数变成min(Ai,x)

• 询问区间[l,r]中所有数的和

• n,m≤50000 分块!(抱歉,我不会!)

• n,m ≤ 500000

裸题,按照上述要求维护一下就可以了,如果想写的话,可以联系我,我这里有我自己出的数据...

给定一个长度为n的数列A,接下来有m次操作:

• 区间[l,r]中的所有数变成min(Ai,x)

• 区间[l,r]中的所有数加上x(x可能是负数)

• 询问区间[l,r]中所有数的和

• n,m≤50000  分块!

• n,m ≤ 500000

同样是裸题,多了一个操作,HDU上有...题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5306

剩下的就是例题时间了!

BZOJ4355: Play with sequence

这个是不是有一点感觉了呢?

分析:其实还是区间操作裸题,我们对于操作1,之间区间覆盖,对于操作2先区间加,再区间取max...其实并不是很难对不对?对于操作3,之间输出1-n的最小值个数(如果最小值是0的话)

附上代码:

#include <queue>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define N 300505
#define ls rt<<1
#define rs rt<<1|1
#define ll long long
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
ll minn[N<<2],minx[N<<2],cn[N<<2],cov[N<<2],add[N<<2];int n,Q;
void PushUp(int rt)
{
if(minn[ls]<minn[rs])minn[rt]=minn[ls],minx[rt]=min(minn[rs],minx[ls]),cn[rt]=cn[ls];
else if(minn[ls]==minn[rs])minn[rt]=minn[ls],minx[rt]=min(minx[rs],minx[ls]),cn[rt]=cn[ls]+cn[rs];
else minn[rt]=minn[rs],minx[rt]=min(minn[ls],minx[rs]),cn[rt]=cn[rs];
}
void PushDown(int m,int rt)
{
if(cov[rt]!=-1)minn[rs]=minn[ls]=cov[ls]=cov[rs]=cov[rt],cn[ls]=(m-(m>>1)),cn[rs]=(m>>1),minx[ls]=minx[rs]=1ll<<62,add[ls]=add[rs]=0,cov[rt]=-1;
if(add[rt])minn[ls]+=add[rt],minn[rs]+=add[rt],minx[ls]+=add[rt],minx[rs]+=add[rt],add[ls]+=add[rt],add[rs]+=add[rt],add[rt]=0;
if(minn[rt]>minn[ls])minn[ls]=minn[rt];if(minn[rt]>minn[rs])minn[rs]=minn[rt];
}
void build(int l,int r,int rt)
{
cov[rt]=-1,add[rt]=0;
if(l==r){scanf("%lld",&minn[rt]),minx[rt]=1ll<<62,cn[rt]=1;return;}
int m=(l+r)>>1;build(lson);build(rson);PushUp(rt);
}
void Update_cov(int L,int R,ll c,int l,int r,int rt)
{
if(L<=l&&r<=R){minn[rt]=cov[rt]=c,minx[rt]=1ll<<62,cn[rt]=r-l+1,add[rt]=0;return;}PushDown(r-l+1,rt);int m=(l+r)>>1;
if(L<=m)Update_cov(L,R,c,lson);if(m<R)Update_cov(L,R,c,rson);PushUp(rt);
}
void Update_add(int L,int R,ll c,int l,int r,int rt)
{
if(L<=l&&r<=R){minn[rt]+=c,add[rt]+=c,minx[rt]+=c;return;}PushDown(r-l+1,rt);int m=(l+r)>>1;
if(L<=m)Update_add(L,R,c,lson);if(m<R)Update_add(L,R,c,rson);PushUp(rt);
}
void Update_max(int L,int R,ll c,int l,int r,int rt)
{
if(c<=minn[rt])return ;
if(L<=l&&r<=R&&minx[rt]>c){minn[rt]=c;return ;}PushDown(r-l+1,rt);int m=(l+r)>>1;
if(L<=m)Update_max(L,R,c,lson);if(m<R)Update_max(L,R,c,rson);PushUp(rt);
}
ll query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)return minn[rt]?0:cn[rt];PushDown(r-l+1,rt);int m=(l+r)>>1;ll ret=0;
if(L<=m)ret+=query(L,R,lson);if(m<R)ret+=query(L,R,rson);return ret;
}
int main()
{
scanf("%d%d",&n,&Q);
build(1,n,1);
while(Q--)
{
int x,y,op;ll z;scanf("%d%d%d",&op,&x,&y);
if(op==1)scanf("%lld",&z),Update_cov(x,y,z,1,n,1);
else if(op==2)scanf("%lld",&z),Update_add(x,y,z,1,n,1),Update_max(x,y,0ll,1,n,1);
else printf("%lld\n",query(x,y,1,n,1));
}
return 0;
}

  好吧好吧...其实例题目前只有一道...目测还有最假女选手什么的...好麻烦的说...

Segment Tree Beats 区间最值问题的更多相关文章

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

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

  2. Segment tree Beats

    Segment tree Beats Segment tree Beats,吉司机线段树,主要是关于如何用线段树实现区间取min/max.我们先看一道例题: HDU5306 Gorgeous Sequ ...

  3. [BZOJ4695]最假女选手:segment tree beats!

    分析 segment tree beats!模板题. 看了gxz的博客突然发现自己写的mxbt和mnbt两个标记没用诶. 代码 #include <bits/stdc++.h> #defi ...

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

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

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

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

  6. 【bzoj4355】Play with sequence 线段树区间最值操作

    题目描述 维护一个长度为N的序列a,现在有三种操作: 1)给出参数U,V,C,将a[U],a[U+1],...,a[V-1],a[V]都赋值为C. 2)给出参数U,V,C,对于区间[U,V]里的每个数 ...

  7. 【hdu5306】Gorgeous Sequence 线段树区间最值操作

    题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y ...

  8. picks loves segment tree I

    picks loves segment tree I 题目背景 来源: \(\text {2018 WC Segment Tree Beats}\) 原作者: \(\text {C_SUNSHINE} ...

  9. SPOJ 11840. Sum of Squares with Segment Tree (线段树,区间更新)

    http://www.spoj.com/problems/SEGSQRSS/ SPOJ Problem Set (classical) 11840. Sum of Squares with Segme ...

随机推荐

  1. Linux CentOS 6.5 下 vsftpd ftp服务器搭建

    Linux CentOS 6.5 下 vsftpd ftp服务器搭建 by:授客 QQ:1033553122   操作系统环境:CentOS 6.5-x86_64 下载地址:http://www.ce ...

  2. SQLServer 学习笔记之超详细基础SQL语句 Part 10

    Sqlserver 学习笔记 by:授客 QQ:1033553122 -----------------------接Part 9------------------- 删除约束的语法 ALTER T ...

  3. Android--监听View的两个指头是放大和缩小

    private double nLenStart = 0;//监听 WebView所用手势 @Override public boolean onTouch(View v, MotionEvent e ...

  4. [iOS]圆形进度条及计时功能

    平时用战网安全令的时候很喜欢圆形倒计时的效果,然后简单看了一下Android的圆形进度条,后来又写了一个IOS的.整体界面参照IOS系统的倒计时功能,顺便熟悉了UIPickerView的一些特性的实现 ...

  5. LeetCode题解之Unique Paths II

    1.题目描述 2.问题描述 使用动态规划算法,加上条件检测即可 3.代码 int uniquePathsWithObstacles(vector<vector<int>>&am ...

  6. EntityFramework 贪婪加载与延迟加载以及资源回收

    EntityFramework的资源回收 1) Using 内包含Entity的上下文关系,对俩表做Add操作,最好可以直接写一个 entity.SaveChanges(); 完成两张表的同时add操 ...

  7. CREATE INDEX (Transact-SQL) 语法 (转载)

    CREATE [ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX index_name ON <object> ( column [ ASC | D ...

  8. 报错:java.net.bindexception: address already in use: jvm_bind:8080

    原因:8080端口被占用 这说明80端口(该端口是Tomcat的监听端口)已经被其他程序占用,先用命令提示符 " netstat -ano " 命令显示端口状态,再在结果中找到端口 ...

  9. EasyUI tree reload时更改参数的问题。

    [问题]很多时候,我们需要重新加载tree数据,不仅仅是简单地刷新,更多的是重定向了URL,其中就包括参数的调整. moduleTree = $('#tree').tree({ queryParams ...

  10. gitlab配置push -f 关闭

    默认路径是/var/opt/gitlab/git-data/repositories/组/库 修改conf 文件 [core] repositoryformatversion = 0 filemode ...