bzoj4695 最假女选手
传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4695
【题解】
SegmentTree beats!(见jiry_2论文/营员交流)
考虑只有对p取max,区间加,查min/和怎么做。
有一道类似的题,是取min,见hdu5306.
按照segmentbeats这套理论,我们要维护最小值,最小值出现个数,次小值即可。
每次区间对$p$取max,如果当前节点满足$min < p < sec$,那么打区间max标记,而且我们也可以很方便算出每个的改变量。
标记下传的话考虑对于$x$的儿子,显然要么满足$p < min$,要么满足$min < p < sec$,直接维护即可。
这里的标记我们不需要开一个tag存,我们只要判断是否满足$min < p < sec$就知道是否下传标记了。
【考虑同时维护min/max的情况】
按照segmentbeats这套理论,我们要维护最小值,最小值出现个数,次小值;最大值,最大值出现个数,次大值即可。
对区间取min操作和上面说的取max操作类似,我们着重讨论标记下传问题。
这里涉及到标记的叠加,稍加讨论下我们发现,只要判断$min < min_x < secmin$就知道是否要把$min_x$传给儿子;同理判断$secmax < max_x < max$就知道是否要把$max_x$传给儿子。
这里还涉及到一个问题:标记下传的先后顺序。
考虑什么时候标记存在影响:因为标记都是对最大值和次大值,最小值和次小值之间的区间打的,其他都是暴力维护,所以只对区间长度小于等于2的情况产生影响。
稍加讨论我们发现,先传和后传是没有影响的。
e.g. 区间 = $[3, 6]$
父区间有标记:对于4取max,对于5取min
那么显然没有影响,正常做即可。
父区间有标记:对于5取max,对于4取min。
我们发现,对于5取max的情况,父区间序列一定变成了$[5, ...]$,这时候再对4取min,不符合标记的性质了,所以不存在这种情况。
复杂度:$O(nlog^2n)$,跑的和$O(nlogn)$差不多。
# include <stdio.h>
# include <string.h>
# include <iostream>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N = 5e5 + , SN = + ;
const int mod = 1e9+, inf = 1e9; inline int getint() {
int x = , f = ; char ch = getchar();
while(!isdigit(ch)) {
if(ch == '-') f = ;
ch = getchar();
}
while(isdigit(ch)) {
x = (x<<) + (x<<) + ch - '';
ch = getchar();
}
return f ? x : -x;
} int n, a[N];
struct node {
int p, t, se;
node () {}
node (int p, int t, int se) : p(p), t(t), se(se) {}
inline friend node combineMax(node a, node b) {
node c;
if(a.p < b.p) {
c.p = b.p; c.t = b.t;
c.se = max(a.p, b.se);
} else if(a.p > b.p) {
c.p = a.p; c.t = a.t;
c.se = max(a.se, b.p);
} else {
c.p = a.p; c.t = a.t + b.t;
c.se = max(a.se, b.se);
}
return c;
}
inline friend node combineMin(node a, node b) {
node c;
if(a.p > b.p) {
c.p = b.p; c.t = b.t;
c.se = min(a.p, b.se);
} else if(a.p < b.p) {
c.p = a.p; c.t = a.t;
c.se = min(a.se, b.p);
} else {
c.p = a.p; c.t = a.t + b.t;
c.se = min(a.se, b.se);
}
return c;
}
inline friend node operator + (node a, int p) {
return node(a.p + p, a.t, a.se + p);
}
}; struct SMTbeats {
node mx[SN], mi[SN];
int tag[SN]; ll s[SN];
# define ls (x<<)
# define rs (x<<|)
inline void up(int x) {
mx[x] = combineMax(mx[ls], mx[rs]);
mi[x] = combineMin(mi[ls], mi[rs]);
s[x] = s[ls] + s[rs];
} // a = max(a, t)
inline void pushmax(int x, int l, int r, int p) {
s[x] += 1ll * mi[x].t * (p - mi[x].p);
mi[x].p = p; mx[x].p = max(mx[x].p, p);
if(mi[x].p == mx[x].p) {
mi[x].se = inf, mx[x].se = -inf;
mi[x].t = mx[x].t = r-l+;
s[x] = 1ll * mi[x].p * (r-l+);
} else mx[x].se = max(mx[x].se, p);
}
// a = min(a, t)
inline void pushmin(int x, int l, int r, int p) {
s[x] += 1ll * mx[x].t * (p - mx[x].p);
mx[x].p = p; mi[x].p = min(mi[x].p, p);
if(mi[x].p == mx[x].p) {
mi[x].se = inf, mx[x].se = -inf;
mi[x].t = mx[x].t = r-l+;
s[x] = 1ll * mi[x].p * (r-l+);
} else mi[x].se = min(mi[x].se, p);
}
inline void pushtag(int x, int l, int r, int p) {
tag[x] += p; s[x] += 1ll * (r-l+) * p;
mx[x] = mx[x] + p, mi[x] = mi[x] + p;
} inline void down(int x, int l, int r) {
int mid = l+r>>;
if(tag[x]) {
pushtag(ls, l, mid, tag[x]); pushtag(rs, mid+, r, tag[x]);
tag[x] = ;
}
if(mx[ls].p > mx[x].p && mx[ls].se < mx[x].p) pushmin(ls, l, mid, mx[x].p);
if(mx[rs].p > mx[x].p && mx[rs].se < mx[x].p) pushmin(rs, mid+, r, mx[x].p);
if(mi[ls].p < mi[x].p && mi[ls].se > mi[x].p) pushmax(ls, l, mid, mi[x].p);
if(mi[rs].p < mi[x].p && mi[rs].se > mi[x].p) pushmax(rs, mid+, r, mi[x].p);
} inline void build(int x, int l, int r) {
tag[x] = ;
if(l == r) {
mx[x].p = mi[x].p = s[x] = a[l], mx[x].t = mi[x].t = , mx[x].se = -inf, mi[x].se = inf;
return ;
}
int mid = l+r>>;
build(ls, l, mid);
build(rs, mid+, r);
up(x);
} inline void edt(int x, int l, int r, int L, int R, int p) {
if(L <= l && r <= R) {
pushtag(x, l, r, p);
return ;
}
down(x, l, r);
int mid = l+r>>;
if(L <= mid) edt(ls, l, mid, L, R, p);
if(R > mid) edt(rs, mid+, r, L, R, p);
up(x);
} inline void edtmin(int x, int l, int r, int L, int R, int p) {
if(mx[x].p <= p) return ;
if(L <= l && r <= R && mx[x].se < p) {
pushmin(x, l, r, p);
return ;
}
down(x, l, r);
int mid = l+r>>;
if(L <= mid) edtmin(ls, l, mid, L, R, p);
if(R > mid) edtmin(rs, mid+, r, L, R, p);
up(x);
} inline void edtmax(int x, int l, int r, int L, int R, int p) {
if(mi[x].p >= p) return ;
if(L <= l && r <= R && mi[x].se > p) {
pushmax(x, l, r, p);
return ;
}
down(x, l, r);
int mid = l+r>>;
if(L <= mid) edtmax(ls, l, mid, L, R, p);
if(R > mid) edtmax(rs, mid+, r, L, R, p);
up(x);
} inline int gmax(int x, int l, int r, int L, int R) {
if(L <= l && r <= R) return mx[x].p;
down(x, l, r);
int mid = l+r>>, ret = -inf;
if(L <= mid) ret = max(ret, gmax(ls, l, mid, L, R));
if(R > mid) ret = max(ret, gmax(rs, mid+, r, L, R));
return ret;
} inline int gmin(int x, int l, int r, int L, int R) {
if(L <= l && r <= R) return mi[x].p;
down(x, l, r);
int mid = l+r>>, ret = inf;
if(L <= mid) ret = min(ret, gmin(ls, l, mid, L, R));
if(R > mid) ret = min(ret, gmin(rs, mid+, r, L, R));
return ret;
} inline ll gsum(int x, int l, int r, int L, int R) {
if(L <= l && r <= R) return s[x];
down(x, l, r);
int mid = l+r>>; ll ret = ;
if(L <= mid) ret += gsum(ls, l, mid, L, R);
if(R > mid) ret += gsum(rs, mid+, r, L, R);
return ret;
} inline void debug(int x, int l, int r) {
printf("%d %d %d [%d %d %d] [%d %d %d] %I64d\n", x, l, r, mx[x].p, mx[x].t, mx[x].se, mi[x].p, mi[x].t, mi[x].se, s[x]);
if (l == r) return ;
int mid = l+r>>;
debug(ls, l, mid);
debug(rs, mid+, r);
} # undef ls
# undef rs
}T; int main() {
n = getint();
for (int i=; i<=n; ++i) a[i] = getint();
T.build(, , n);
int Q, op, l, r, x; cin >> Q;
while(Q--) {
// T.debug(1, 1, n);
op = getint(), l = getint(), r = getint();
if(op == ) {
x = getint();
T.edt(, , n, l, r, x);
} else if(op == ) {
x = getint();
T.edtmax(, , n, l, r, x);
} else if(op == ) {
x = getint();
T.edtmin(, , n, l, r, x);
} else if(op == ) printf("%lld\n", T.gsum(, , n, l, r));
else if(op == ) printf("%d\n", T.gmax(, , n, l, r));
else printf("%d\n", T.gmin(, , n, l, r));
}
return ;
}
bzoj4695 最假女选手的更多相关文章
- BZOJ4695 最假女选手(势能线段树)
BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...
- 2018.07.27 bzoj4695: 最假女选手(线段树)
传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...
- [BZOJ4695]最假女选手:segment tree beats!
分析 segment tree beats!模板题. 看了gxz的博客突然发现自己写的mxbt和mnbt两个标记没用诶. 代码 #include <bits/stdc++.h> #defi ...
- bzoj4695 最假女选手(势能线段树/吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)给一个区间\([L,R]\) 加上一个数\(x\) \(2.\)把一个区间\([L,R]\) 里小于\(x\) 的数变成\(x\) \(3.\ ...
- bzoj 4695 最假女选手 吉利线段树
最假女选手 Time Limit: 50 Sec Memory Limit: 128 MBSubmit: 480 Solved: 118[Submit][Status][Discuss] Desc ...
- 【bzoj4695】最假女选手 线段树区间最值操作
题目描述 给定一个长度为 N 序列,编号从 1 到 N .要求支持下面几种操作:1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于 ...
- 【bzoj4695】最假女选手
zcy的励志故事.jpg 傻逼zcy突然想立一个flag,写一个segment-tree-beats的题娱乐一下 于是他就想起了这道题. 他打算今晚写完 然后光是写他就写的头昏脑涨,还犯了询问写反这种 ...
- BZOJ4695:最假女选手
浅谈区间最值操作和历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html 题目传送门:https://lydsy.com/JudgeOnline/pr ...
- (WC2016模拟十一)【BZOJ4695】最假女选手
ps:好久没更博啦……这几天连着有模拟赛,等初赛前后休息的时候来疯狂补坑吧……顺便补一下前面的数论啥的? 题解: mdzz我场上写了个15分暴力长度跟标算差不多... 线段树大法好啊!这题听说很多人做 ...
随机推荐
- 算法与数据结构实验题 4.1 伊姐姐数字 game
★实验任务 伊姐姐热衷于各类数字游戏,24 点.2048.数独等轻轻松松毫无压力.一 日,可爱的小姐姐邀请伊姐姐一起玩一种简单的数字 game,游戏规则如下: 一开始桌上放着 n 张数字卡片,从左到右 ...
- 二叉树及其遍历方法---python实现
github:代码实现 本文算法均使用python3实现 1. 二叉树 1.1 二叉树的定义 二叉树是一种特殊的树,它具有以下特点: (1)树中每个节点最多只能有两棵树,即每个节点的度最多为2 ...
- 【Linux】- vi/vim
所有的 Unix Like 系统都会内建 vi 文书编辑器,其他的文书编辑器则不一定会存在. 但是目前我们使用比较多的是 vim 编辑器. vim 具有程序编辑的能力,可以主动的以字体颜色辨别语法的正 ...
- 错误 10 非静态的字段、方法或属性“Test10.Program.a”要求对象引用
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Test ...
- 在windows搭建react
1.安装必须的软件 1.Python 2 注意勾选 Add python.exe to Path,选项,这样就可以在安装完成后,不用手动去添加环境变量 安装完,打开cmd.exe,输入py ...
- 显示系统中所有的socket信息
netstat -aon /proc/net/tcp /proc/net/udp /proc/net/unix 相关的代码是:tcp4_seq_show(struct seq_file *file, ...
- [OS] 信号量(Semaphore)
一个信号量S是一个整型量,除对其初始化外,它只能由两个原子操作P和V来访问.P和V的名称来源于荷兰文proberen(测试)和verhogen(增量),后面亦将P/V操作分别称作wait(), sig ...
- iOS-系统 图片、视频 管理控制器UIImagePickerController
UIImagePickerController 是一个管理系统多媒体文件库(相册)中的图片.视频文件的视图控制器,诞生于iOS4之前,虽然功能不是很完善,我们仍可以用这个视图控制器做一些有创造 ...
- 【Luogu】P2901牛慢跑(K短路模板)
题目链接 K短路居然用A*……奇妙. 先建反图从终点(1)跑一遍最短路,再A*,用堆存当前点到终点距离+从起点到当前点距离. 每次取出终点都可以视为发现了一个新的最短路. #include<cs ...
- Python 源码剖析(三)【字符串对象】
三.字符串对象 1.PyStringObject与PyString_Type 2.创建PyStringObject对象 3.Intern 机制 4.字符缓冲池 5.PyStringObject 效率相 ...