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分暴力长度跟标算差不多... 线段树大法好啊!这题听说很多人做 ...
随机推荐
- 20145214 《Java程序设计》第9周学习总结
20145214 <Java程序设计>第9周学习总结 教材学习内容总结 JDBC简介 JDBC全名Java DataBase Connectivity,是java联机数据库的标准规范.它定 ...
- SpringMVC拦截器实现登录认证(转发)
感谢原作者,转发自:http://blog.csdn.net/u014427391/article/details/51419521 以Demo的形式讲诉拦截器的使用 项目结构如图: 需要的jar:有 ...
- 项目UML设计--日不落战队
[团队信息] 团队项目: 小葵日记--主打记录与分享模式的日记app 队名:日不落战队 队员信息及贡献分比例: 短学号 名 本次作业博客链接 此次作业任务 贡献分配 备注 501 安琪 http:// ...
- OSG学习:转动的小汽车示例
由于只是简单的示例,所以小汽车的模型也比较简单,是由简单的几何体组成. 代码如下: #include <osg\ShapeDrawable> #include <osg\Animat ...
- SpringBoot Web(SpringMVC)
入门工程: package com.example.demo.controller; import com.example.demo.entity.User; import org.springfra ...
- Spline样条函数 //C++关键字:operator // 重载函数 // 隐含的this指针 // 指针和const限定符
在数学学科数值分析中,样条是一种特殊的函数,由多项式分段定义.样条插值是使用一种名为样条的特殊分段多项式进行插值的形式.由于样条插值可以使用低阶多项式样条实现较小的差值误差,这样就避免了使用高阶多项式 ...
- python的if语句、while循环、for循环
if语句 计算机又被称作电脑,意指计算机可以像人脑一样,根据周围环境条件(即expession)的变化做出不同的反应(即执行代码)if语句就是来控制计算机实现这一功能 语法: 1.单分支,单个条件判断 ...
- hadoop SequenceFile示例
1.写入,SequenceFile的key和value不一定是Writable,只要能被Serialization序列化和反序列化就可以. private static final String[] ...
- Oracle 以某字段分组,以某字段排序,取前几条
select * from (select row_number() over(partition by 以此字段为分组 order by 以此字段排序 desc rn from dual) whe ...
- [洛谷P4721]【模板】分治 FFT
题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$f_i=\sum_{j=1}^if_{i-j}g_j\\f_0=1$$ 题解:直接求复杂度是$O(n^ ...