【bzoj4355】Play with sequence 线段树区间最值操作
题目描述
输入
输出
样例输入
5 3
6 4 6 6 4
2 1 5 -5
1 3 4 4
3 1 5
样例输出
2
题解
线段树区间最值操作
考虑到操作1的 $C\le 0$ ,因此 $0$ 只可能出现在最小值。所以要统计 $0$ 的个数,只需要统计:最小值是不是0、最小值个数即可。
对于操作1直接区间赋值,操作2我们拆成两个操作:区间+C直接加,区间最大值操作参考 吉老师的Segment tree Beats! ,维护最小值、严格次小值即可。
注意标记下传顺序:区间赋值>区间加>区间最大操作。
同样,区间最大操作可以不维护标记,直接下传最小值。
时间复杂度 $O(n\log^2 n)$ (吉老师表示PPT里的证明是萎的...复杂度证明参考集训队论文)
#include <cstdio>
#include <algorithm>
#define N 1200010
#define inf 1ll << 62
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
ll mn[N] , se[N] , cov[N] , add[N];
int mc[N];
inline void pushup(int x)
{
int ls = x << 1 , rs = x << 1 | 1;
if(mn[ls] < mn[rs]) mn[x] = mn[ls] , mc[x] = mc[ls] , se[x] = min(se[ls] , mn[rs]);
if(mn[ls] > mn[rs]) mn[x] = mn[rs] , mc[x] = mc[rs] , se[x] = min(mn[ls] , se[rs]);
if(mn[ls] == mn[rs]) mn[x] = mn[ls] , mc[x] = mc[ls] + mc[rs] , se[x] = min(se[ls] , se[rs]);
}
inline void pushdown(int l , int r , int x)
{
int ls = x << 1 , rs = x << 1 | 1;
if(~cov[x])
{
int mid = (l + r) >> 1;
mn[ls] = cov[x] , mc[ls] = mid - l + 1 , se[ls] = inf , cov[ls] = cov[x] , add[ls] = 0;
mn[rs] = cov[x] , mc[rs] = r - mid , se[rs] = inf , cov[rs] = cov[x] , add[rs] = 0;
cov[x] = -1;
}
if(add[x])
{
mn[ls] += add[x] , se[ls] += add[x] , add[ls] += add[x];
mn[rs] += add[x] , se[rs] += add[x] , add[rs] += add[x];
add[x] = 0;
}
if(mn[ls] < mn[x]) mn[ls] = mn[x];
if(mn[rs] < mn[x]) mn[rs] = mn[x];
}
void build(int l , int r , int x)
{
cov[x] = -1;
if(l == r)
{
scanf("%lld" , &mn[x]) , mc[x] = 1 , se[x] = inf;
return;
}
int mid = (l + r) >> 1;
build(lson) , build(rson);
pushup(x);
}
void cover(int b , int e , ll c , int l , int r , int x)
{
if(b <= l && r <= e)
{
mn[x] = c , mc[x] = r - l + 1 , se[x] = inf , cov[x] = c , add[x] = 0;
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) cover(b , e , c , lson);
if(e > mid) cover(b , e , c , rson);
pushup(x);
}
void update(int b , int e , ll a , int l , int r , int x)
{
if(b <= l && r <= e)
{
mn[x] += a , se[x] += a , add[x] += a;
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) update(b , e , a , lson);
if(e > mid) update(b , e , a , rson);
pushup(x);
}
void vmax(int b , int e , int l , int r , int x)
{
if(mn[x] >= 0) return;
if(b <= l && r <= e && se[x] > 0)
{
mn[x] = 0;
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) vmax(b , e , lson);
if(e > mid) vmax(b , e , rson);
pushup(x);
}
int query(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return mn[x] ? 0 : mc[x];
pushdown(l , r , x);
int mid = (l + r) >> 1 , ans = 0;
if(b <= mid) ans += query(b , e , lson);
if(e > mid) ans += query(b , e , rson);
return ans;
}
int main()
{
int n , m , opt , x , y;
ll z;
scanf("%d%d" , &n , &m);
build(1 , n , 1);
while(m -- )
{
scanf("%d%d%d" , &opt , &x , &y);
if(opt == 1) scanf("%lld" , &z) , cover(x , y , z , 1 , n , 1);
if(opt == 2) scanf("%lld" , &z) , update(x , y , z , 1 , n , 1) , vmax(x , y , 1 , n , 1);
if(opt == 3) printf("%d\n" , query(x , y , 1 , n , 1));
}
return 0;
}
【bzoj4355】Play with sequence 线段树区间最值操作的更多相关文章
- 【hdu5306】Gorgeous Sequence 线段树区间最值操作
题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y ...
- HDU 5306 Gorgeous Sequence[线段树区间最值操作]
Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 【bzoj4695】最假女选手 线段树区间最值操作
题目描述 给定一个长度为 N 序列,编号从 1 到 N .要求支持下面几种操作:1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于 ...
- HUD.2795 Billboard ( 线段树 区间最值 单点更新 单点查询 建树技巧)
HUD.2795 Billboard ( 线段树 区间最值 单点更新 单点查询 建树技巧) 题意分析 题目大意:一个h*w的公告牌,要在其上贴公告. 输入的是1*wi的w值,这些是公告的尺寸. 贴公告 ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间取摸
D. The Child and Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest ...
- HDU 3911 Black And White(线段树区间合并+lazy操作)
开始以为是水题,结果...... 给你一些只有两种颜色的石头,0为白色,1为黑色. 然后两个操作: 1 l r 将[ l , r ]内的颜色取反 0 l r 计算[ l , r ]内最长连续黑色石头的 ...
- UVA 1400."Ray, Pass me the dishes!" -分治+线段树区间合并(常规操作+维护端点)并输出最优的区间的左右端点-(洛谷 小白逛公园 升级版)
"Ray, Pass me the dishes!" UVA - 1400 题意就是线段树区间子段最大和,线段树区间合并,但是这道题还要求输出最大和的子段的左右端点.要求字典序最小 ...
- cf834D(dp+线段树区间最值,区间更新)
题目链接: http://codeforces.com/contest/834/problem/D 题意: 每个数字代表一种颜色, 一个区间的美丽度为其中颜色的种数, 给出一个有 n 个元素的数组, ...
- Codeforces Round #250 (Div. 1) D. The Child and Sequence 线段树 区间求和+点修改+区间取模
D. The Child and Sequence At the children's day, the child came to Picks's house, and messed his h ...
随机推荐
- python 生成随机长度的字符串
import os def randomString(n): return (''.join(map(lambda xx:(hex(ord(xx))[2:]),os.urandom(n))))[0:1 ...
- vue 与原生app的对接交互(混合开发)
小伙伴们在用vue开发h5项目特别是移动端的项目,很多都是打包后挂载在原生APP上的,那就少不了与原生交互了,我最近就是在坐这个,踩了一些坑,拿出来给大家分享下. 0.通过url传输数据:(一般是在入 ...
- 在spring boot上基于maven使用redis——批量匹配并删除 (二)
一.背景 在搭建了项目之后,由于需要通过触发动作,并删除redis中多个key. 二.思路 在查询了jedis并没有类似的删除方法之后,事情就变得清晰起来.完成上述任务,分为两个步骤,第一,找到要删除 ...
- Linux工作管理
工作管理? 其实也就是把程序放到后台来管理,在windows中也就是最小化,在Linux中是通过命令把程序放到后台中.jobs命令查看后台程序. 对于第一点注意事项,mysql启动是例外的,要是叉掉了 ...
- fastdfs+nginx+image_filter安装与生成缩略图
fastdfs简介 类似google FS的一个轻量级分布式文件系统,纯C实现,支持linux.FreeBSD等UNIX系统: 只能通过API访问,不支持POXIS: 文件不分块存储,上传的文件和OS ...
- Consul 架构(译)
Consul 架构 此篇文章主要对consul的相关内部技术细节进行简要概述. »术语 代理 - 代理是指consul集群中运行的consul实例,通过执行 consul agent 命令来启动. 代 ...
- Linux内核学习笔记(3)-- 进程的创建和终结
一. 进程创建: Unix 下的进程创建很特别,与许多其他操作系统不同,它分两步操作来创建和执行进程: fork() 和 exec() .首先,fork() 通过拷贝当前进程创建一个子进程:然后,ex ...
- Numpy入门笔记第二天
# 数组的组合 import numpy as np arr1 = np.arange(5) arr2 = np.arange(3) print arr1 print arr2 [0 1 2 3 4] ...
- python_MySQL 数据库操作
Python中的mysql操作可以使用MySQLdb模块来完成.它符合Python社区设计的Python Database API SpecificationV2.0标准,所以与其他的数据库操作的AP ...
- 进阶系列(8)——匿名方法与lambda表达式
一 匿名方法的介绍 匿名方法是为了简化委托的实现,方便调用委托方法而出现的,同时,匿名方法也是学好lambda表达式的基础.在委托调用的方法中,如果方法只被调用一次,这个时候我们就没有必要创建 ...