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分暴力长度跟标算差不多... 线段树大法好啊!这题听说很多人做 ...
随机推荐
- <Android>tab选项卡
1.继承TabActivity实现 a) 在布局文件中使用FrameLayout列出Tab组件及Tab中的内容组件 b) Activity要继承TabActivity c ...
- Python的7种性能测试工具:timeit、profile、cProfile、line_profiler、memory_profiler、PyCharm图形化性能测试工具、objgraph
1.timeit: >>> import timeit >>> def fun(): ): a = i * i >>> timeit.timeit ...
- DELPHI BOOKMARK使用
关于书签(BookMark)操作: 书签操作主要用于在表中快速地定位记录指针,在应用程序中常常要保存记录指针所在的位置,在进行其他处理之后,希望能快速地返回到先前指针所在的位置,此时,使用 ...
- WPF文件和文件夹的操作
1.对文件的操作 private void button_chose_Click(object sender, RoutedEventArgs e) { var openFileDialog = ne ...
- 【Asp.Net】IIS应用程序池添加ASP.NET v4.0
可能在安装.NET Framewrok 4.0之前,IIS就已经装好了,结果在IIS的应用程序池中只有.NET 2.0的Classic .NET AppPool和DefaultAppPool.在使用v ...
- Lucene笔记一
Lucene就是一个全文检索的工具,建立索引用的,类似于新华字典的目录 这里使用的是lucene-4.4.0版本,入门代码所需jar包如下图所示(解压lucene-4.4.0后的目录): 入门代码: ...
- 使用mac电脑,对Github客户端的简单操作1----开源项目
工作之余自己也会一写一些小的程序项目,由于一直没时间“折腾”开源,之前写博客都是直接粘代码片段,今天看别人写技术博客大都会放出项目Github地址,突然感觉自己有点点out and low,作为一个励 ...
- 【bzoj1202】[HNOI2005]狡猾的商人 带权并查集
题目描述 刁姹接到一个任务,为税务部门调查一位商人的账本,看看账本是不是伪造的.账本上记录了n个月以来的收入情况,其中第i 个月的收入额为Ai(i=1,2,3...n-1,n), .当 Ai大于0时表 ...
- (转)超详细单机版搭建hadoop环境图文解析
超详细单机版搭建hadoop环境图文解析 安装过程: 一.安装Linux操作系统 二.在Ubuntu下创建hadoop用户组和用户 三.在Ubuntu下安装 ...
- 【题解】NOI2016区间
Two - pointer 第一题…… 大概就是对于一段连续的区间求解,使用两个指针不断卡区间的长度直到区间不满足条件吧. 这题只要对区间以长度从小到大排一下序,然后使用两个指针指向区间.线段树维护被 ...