【bzoj4695】最假女选手 线段树区间最值操作
题目描述
给定一个长度为 N 序列,编号从 1 到 N 。要求支持下面几种操作:
1.给一个区间[L,R] 加上一个数x
2.把一个区间[L,R] 里小于x 的数变成x
3.把一个区间[L,R] 里大于x 的数变成x
4.求区间[L,R] 的和
5.求区间[L,R] 的最大值
6.求区间[L,R] 的最小值
输入
输出
样例输入
2
1 2
2
2 1 2 2
4 1 2
样例输出
4
题解
线段树区间最值操作
维护区间最小值、最小值个数、严格次小值、最大值、最大值个数、严格次大值、区间和、区间加和标记即可。。。
还要注意,修改区间最小值时要注意其对最大值、严格次大值是否有影响,修改区间最大值时要注意其对最小值、严格次小值的影响。
想想都觉得麻烦。。。
时间复杂度 $O(n\log^2n)$
注意本题略微卡常,不能全用long long,只有区间和使用long long维护。
#include <cstdio>
#include <algorithm>
#define N 2000010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
const int inf = 1 << 30;
int mx[N] , cx[N] , sx[N] , mn[N] , cn[N] , sn[N] , add[N];
ll sum[N];
inline void pushup(int x)
{
int ls = x << 1 , rs = x << 1 | 1;
sum[x] = sum[ls] + sum[rs];
if(mx[ls] > mx[rs]) mx[x] = mx[ls] , cx[x] = cx[ls] , sx[x] = max(sx[ls] , mx[rs]);
if(mx[ls] < mx[rs]) mx[x] = mx[rs] , cx[x] = cx[rs] , sx[x] = max(mx[ls] , sx[rs]);
if(mx[ls] == mx[rs]) mx[x] = mx[ls] , cx[x] = cx[ls] + cx[rs] , sx[x] = max(sx[ls] , sx[rs]);
if(mn[ls] < mn[rs]) mn[x] = mn[ls] , cn[x] = cn[ls] , sn[x] = min(sn[ls] , mn[rs]);
if(mn[ls] > mn[rs]) mn[x] = mn[rs] , cn[x] = cn[rs] , sn[x] = min(mn[ls] , sn[rs]);
if(mn[ls] == mn[rs]) mn[x] = mn[ls] , cn[x] = cn[ls] + cn[rs] , sn[x] = min(sn[ls] , sn[rs]);
}
inline void pushdown(int l , int r , int x)
{
int ls = x << 1 , rs = x << 1 | 1;
if(add[x])
{
int mid = (l + r) >> 1;
mx[ls] += add[x] , sx[ls] += add[x] , mn[ls] += add[x] , sn[ls] += add[x] , sum[ls] += (mid - l + 1) * add[x] , add[ls] += add[x];
mx[rs] += add[x] , sx[rs] += add[x] , mn[rs] += add[x] , sn[rs] += add[x] , sum[rs] += (r - mid) * add[x] , add[rs] += add[x];
add[x] = 0;
}
if(mx[ls] > mx[x])
{
if(mn[ls] == mx[ls]) mn[ls] = mx[x];
if(sn[ls] == mx[ls]) sn[ls] = mx[x];
sum[ls] += 1ll * (mx[x] - mx[ls]) * cx[ls] , mx[ls] = mx[x];
}
if(mx[rs] > mx[x])
{
if(mn[rs] == mx[rs]) mn[rs] = mx[x];
if(sn[rs] == mx[rs]) sn[rs] = mx[x];
sum[rs] += 1ll * (mx[x] - mx[rs]) * cx[rs] , mx[rs] = mx[x];
}
if(mn[ls] < mn[x])
{
if(mx[ls] == mn[ls]) mx[ls] = mn[x];
if(sx[ls] == mn[ls]) sx[ls] = mn[x];
sum[ls] += 1ll * (mn[x] - mn[ls]) * cn[ls] , mn[ls] = mn[x];
}
if(mn[rs] < mn[x])
{
if(mx[rs] == mn[rs]) mx[rs] = mn[x];
if(sx[rs] == mn[rs]) sx[rs] = mn[x];
sum[rs] += 1ll * (mn[x] - mn[rs]) * cn[rs] , mn[rs] = mn[x];
}
}
void build(int l , int r , int x)
{
if(l == r)
{
scanf("%lld" , &sum[x]) , mx[x] = mn[x] = sum[x] , cx[x] = cn[x] = 1 , sx[x] = -inf , sn[x] = inf;
return;
}
int mid = (l + r) >> 1;
build(lson) , build(rson);
pushup(x);
}
void vadd(int b , int e , int a , int l , int r , int x)
{
if(b <= l && r <= e)
{
mx[x] += a , sx[x] += a , mn[x] += a , sn[x] += a , sum[x] += 1ll * (r - l + 1) * a , add[x] += a;
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) vadd(b , e , a , lson);
if(e > mid) vadd(b , e , a , rson);
pushup(x);
}
void vmax(int b , int e , int a , int l , int r , int x)
{
if(mn[x] >= a) return;
if(b <= l && r <= e && sn[x] > a)
{
if(mx[x] == mn[x]) mx[x] = a;
if(sx[x] == mn[x]) sx[x] = a;
sum[x] += 1ll * (a - mn[x]) * cn[x] , mn[x] = a;
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) vmax(b , e , a , lson);
if(e > mid) vmax(b , e , a , rson);
pushup(x);
}
void vmin(int b , int e , int a , int l , int r , int x)
{
if(mx[x] <= a) return;
if(b <= l && r <= e && sx[x] < a)
{
if(mn[x] == mx[x]) mn[x] = a;
if(sn[x] == mx[x]) sn[x] = a;
sum[x] += 1ll * (a - mx[x]) * cx[x] , mx[x] = a;
return;
}
pushdown(l , r , x);
int mid = (l + r) >> 1;
if(b <= mid) vmin(b , e , a , lson);
if(e > mid) vmin(b , e , a , rson);
pushup(x);
}
ll qsum(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return sum[x];
pushdown(l , r , x);
int mid = (l + r) >> 1; ll ans = 0;
if(b <= mid) ans += qsum(b , e , lson);
if(e > mid) ans += qsum(b , e , rson);
return ans;
}
int qmax(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return mx[x];
pushdown(l , r , x);
int mid = (l + r) >> 1 , ans = -inf;
if(b <= mid) ans = max(ans , qmax(b , e , lson));
if(e > mid) ans = max(ans , qmax(b , e , rson));
return ans;
}
int qmin(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return mn[x];
pushdown(l , r , x);
int mid = (l + r) >> 1 , ans = inf;
if(b <= mid) ans = min(ans , qmin(b , e , lson));
if(e > mid) ans = min(ans , qmin(b , e , rson));
return ans;
}
int main()
{
int n , m , opt , x , y , z;
scanf("%d" , &n);
build(1 , n , 1);
scanf("%d" , &m);
while(m -- )
{
scanf("%d%d%d" , &opt , &x , &y);
if(opt == 1) scanf("%d" , &z) , vadd(x , y , z , 1 , n , 1);
if(opt == 2) scanf("%d" , &z) , vmax(x , y , z , 1 , n , 1);
if(opt == 3) scanf("%d" , &z) , vmin(x , y , z , 1 , n , 1);
if(opt == 4) printf("%lld\n" , qsum(x , y , 1 , n , 1));
if(opt == 5) printf("%d\n" , qmax(x , y , 1 , n , 1));
if(opt == 6) printf("%d\n" , qmin(x , y , 1 , n , 1));
}
return 0;
}
【bzoj4695】最假女选手 线段树区间最值操作的更多相关文章
- 【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]里的每个数 ...
- 【hdu5306】Gorgeous Sequence 线段树区间最值操作
题目描述 给你一个序列,支持三种操作: $0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ :$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值:$2\ x\ y ...
- BZOJ.4695.最假女选手(线段树 Segment tree Beats!)
题目链接 区间取\(\max,\ \min\)并维护区间和是普通线段树无法处理的. 对于操作二,维护区间最小值\(mn\).最小值个数\(t\).严格次小值\(se\). 当\(mn\geq x\)时 ...
- BZOJ 4695 最假女选手 线段树
题意: 给定一个长度为 N序列,编号从1 到 N.要求支持下面几种操作: 1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于x ...
- HDU 5306 Gorgeous Sequence[线段树区间最值操作]
Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- HUD.2795 Billboard ( 线段树 区间最值 单点更新 单点查询 建树技巧)
HUD.2795 Billboard ( 线段树 区间最值 单点更新 单点查询 建树技巧) 题意分析 题目大意:一个h*w的公告牌,要在其上贴公告. 输入的是1*wi的w值,这些是公告的尺寸. 贴公告 ...
- 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 个元素的数组, ...
随机推荐
- [并发并行]_[线程模型]_[Pthread线程使用模型之二 工作组work crew]
Pthread线程使用模型之二工作组(Work crew) 场景 1.一些耗时的任务,比如分析多个类型的数据, 是独立的任务, 并不像 pipeline那样有序的依赖关系, 这时候pipeline就显 ...
- charles录制https请求
之前一直用windows系统,抓包什么的都是用的fiddler或者wireshark,操作比较简单,扩展性也比较强,现在因为工作原因换了mac,在网上一直没有找到fiddler的mac版本,就只能切换 ...
- ubuntu18.04安装mongoDB 4.0
STEP 1: 在终端输入GPK码 $ sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334B ...
- 【UGUI】 (二)--------- 小地图
在绝大多数游戏中,小地图都是极为常见的一个模块而且十分重要.在Unity里面如何制作一个地图其实也是比较简单的 一. 创建玩家与敌人 创建一个Capsule,命名为Player,代表我们的游戏玩家,创 ...
- 三、Django之请求与响应-Part 1
一.新建项目 进入你指定的项目保存目录,然后运行下面的命令: $ django-admin startproject mysite 这将在目录下生成一个mysite目录,也就是你的这个Django项目 ...
- KRKR基础篇(二)
这里介绍一些krkr的语法规范,具体的命令含义及用法以后再叙述 一:kag语法及基本概念 KAG使用的剧本语言为KAG Script,文件扩展名为.ks 脚本内的文字除 注释, 命令 , 段落标 ...
- HashMap 和 HashTable 到底哪不同 ?
HashMap 和 HashTable 到底哪不同 ? 2017/05/29 | 分类: 基础技术 | 1 条评论 | 标签: HASHMAP, HASHTABLE 分享到: 原文出处: 程序员赵鑫 ...
- docker应用容器化准则—12 factor
在云的时代,越来越多的传统应用需要迁移到云环境下,新应用也要求能适应云的架构设计和开发模式.而12-factor提供了一套标准的云原生应用开发的最佳原则. 在容器云项目中应用容器化主要参考12-Fac ...
- UVA 11542 高斯消元
从数组中选择几个数,要求他们的乘积可以开平方,问有多少种方案. 先将单个数拆分成质因子,对于这个数而言,那些指数为奇数的质因子会使这个数无法被开平方. 所以我们需要选择一个对应质因子指数为奇数的元素, ...
- java运行时内存分类
主要有java栈(虚拟机栈), 堆 ,方法区. 线程私有: 栈: 每个方法执行的时候 都会同时创建一个栈桢 Stack Frame 用于存储 局部变量表, 操作数栈,动态链接, 方法出口等信息 线程 ...