【hdu5306】Gorgeous Sequence 线段树区间最值操作
给你一个序列,支持三种操作:
$0\ x\ y\ t$ :将 $[x,y]$ 内大于 $t$ 的数变为 $t$ ;
$1\ x\ y$ :求 $[x,y]$ 内所有数的最大值;
$2\ x\ y$ :求 $[x,y]$ 内所有数的和。
多组测试数据,$\sum n,\sum m\le 10^6$
题解
线段树区间最值操作
对于线段树上的一个节点,维护对应区间的:最大值 $mx$ 、最大值个数 $c$ 及严格次大值 $se$ 。那么对于一次区间最小值操作:
如果 $t\ge mx$ ,则这个操作不会对区间产生影响,直接退出;
如果 $se<t<mx$ ,则这个操作只会对区间最大值产生影响,区间和减小 $c(mx-t)$ ,最大值变为 $t$ ,打标记退出;
否则,无法直接计算贡献,递归子树处理。
其中第二种情况的 “打标记” 实际上就是下传新的最大值,因此可以不打标记,直接将最大值下传。
这样做的时间复杂度是 $O(n\log n)$ 的,证明参考 吉老师的Segment tree Beats!
#include <cstdio>
#include <algorithm>
#define N 1000010
#define lson l , mid , x << 1
#define rson mid + 1 , r , x << 1 | 1
using namespace std;
typedef long long ll;
ll mx[N << 2] , c[N << 2] , se[N << 2] , sum[N << 2];
inline void vmin(ll v , int x)
{
if(mx[x] > v) sum[x] -= c[x] * (mx[x] - v) , mx[x] = v;
}
inline void pushup(int x)
{
int l = x << 1 , r = x << 1 | 1;
sum[x] = sum[l] + sum[r];
if(mx[l] > mx[r]) mx[x] = mx[l] , c[x] = c[l] , se[x] = max(se[l] , mx[r]);
if(mx[l] < mx[r]) mx[x] = mx[r] , c[x] = c[r] , se[x] = max(mx[l] , se[r]);
if(mx[l] == mx[r]) mx[x] = mx[l] , c[x] = c[l] + c[r] , se[x] = max(se[l] , se[r]);
}
inline void pushdown(int x)
{
vmin(mx[x] , x << 1) , vmin(mx[x] , x << 1 | 1);
}
void build(int l , int r , int x)
{
if(l == r)
{
scanf("%lld" , &mx[x]) , sum[x] = mx[x] , c[x] = 1 , se[x] = -1;
return;
}
int mid = (l + r) >> 1;
build(lson) , build(rson);
pushup(x);
}
void update(int b , int e , ll v , int l , int r , int x)
{
if(mx[x] <= v) return;
if(b <= l && r <= e && se[x] < v)
{
vmin(v , x);
return;
}
pushdown(x);
int mid = (l + r) >> 1;
if(b <= mid) update(b , e , v , lson);
if(e > mid) update(b , e , v , rson);
pushup(x);
}
ll qmax(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return mx[x];
pushdown(x);
int mid = (l + r) >> 1;
ll ans = 0;
if(b <= mid) ans = max(ans , qmax(b , e , lson));
if(e > mid) ans = max(ans , qmax(b , e , rson));
return ans;
}
ll qsum(int b , int e , int l , int r , int x)
{
if(b <= l && r <= e) return sum[x];
pushdown(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 main()
{
int T;
scanf("%d" , &T);
while(T -- )
{
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 == 0) scanf("%lld" , &z) , update(x , y , z , 1 , n , 1);
if(opt == 1) printf("%lld\n" , qmax(x , y , 1 , n , 1));
if(opt == 2) printf("%lld\n" , qsum(x , y , 1 , n , 1));
}
}
return 0;
}
【hdu5306】Gorgeous Sequence 线段树区间最值操作的更多相关文章
- HDU 5306 Gorgeous Sequence[线段树区间最值操作]
Gorgeous Sequence Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Othe ...
- 【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]里的每个数 ...
- 【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 ...
- cf834D(dp+线段树区间最值,区间更新)
题目链接: http://codeforces.com/contest/834/problem/D 题意: 每个数字代表一种颜色, 一个区间的美丽度为其中颜色的种数, 给出一个有 n 个元素的数组, ...
- 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 题意就是线段树区间子段最大和,线段树区间合并,但是这道题还要求输出最大和的子段的左右端点.要求字典序最小 ...
- HDU-1754I Hate It 线段树区间最值
这道题比较基本,就是用线段树维护区间最值,可以算是模板吧-.. I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768 ...
随机推荐
- 20155334 2016-2017-2 《Java程序设计》第三周学习总结
20155334 2016-2017-2 <Java程序设计>第三周学习总结 教材学习内容总结 第四章: 讲的是类类型,使用java撰写程序几乎都在使用对象(Object),要产生对象必须 ...
- 【java笔记】Calendar.getInstance()是什么意思
Calendar类是个抽象类,因此本身不能被实例化,然而在却创建了Calendar 的对象,但并不是抽象类可以创建对象这个对象并不是Calendar 自身实例,而是其子类实例,这是在getInstan ...
- ELKStack入门篇(一)之ELK部署和使用
一.ELKStack简介 1.ELK介绍 中文指南:https://www.gitbook.com/book/chenryn/elk-stack-guide-cn/details ELK Stack包 ...
- directive 指令一
什么是Directive Directive将一段html,js封装在一起,形成一个可以复用的独立个体,具有特定的功能.angularjs中的指令通常是比较小的组件,它相当于是给我们提供了一些公共的自 ...
- jquery.validate使用 - 5
一些常用的验证脚本 不会写js了,只能从网上找一些常用的验证脚本. // 手机号码验证jQuery.validator.addMethod("mobile", function(v ...
- flume 安装过程记录
1.安装jdk 2.下载安装包 : apache-flume-1.7.0-bin.tar.gz 安装包是在win下载的,需要拖动到ubuntu下的/home/hadoop (拖动不了需要先安装 lr ...
- 基于OpenSSL的RSA加密应用(非算法)
基于OpenSSL的RSA加密应用(非算法) iOS开发中的小伙伴应该是经常用der和p12进行加密解密,而且在通常加密不止一种加密算法,还可以加点儿盐吧~本文章主要阐述的是在iOS中基于openSL ...
- Maven学习(七)-----Maven添加远程仓库
Maven添加远程仓库 默认情况下,Maven从Maven中央仓库下载所有依赖关系.但是,有些库丢失在中央存储库,只有在Java.net或JBoss的储存库远程仓库中能找到. 1. Java.net资 ...
- NTP(Network Time Protocol)
Linux NTP配置详解 (Network Time Protocol) http://www.ntp.org/ Meinberg NTP packages provide a GUI instal ...
- git clone、git pull和git fetch的用法及区别
声明:码字不易,转载请注明出处,欢迎文章下方讨论交流.Git 常用命令速查表 最近在一个学习小组里学习AI的课程,我们所有的学习资料和homework都放在gitlab上.今天一个小队友从gitlab ...