传送门: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 最假女选手的更多相关文章

  1. BZOJ4695 最假女选手(势能线段树)

    BZOJ题目传送门 终于体会到初步掌握势能分析思想的重要性了. 一开始看题,感觉套路还是很一般啊qwq.直接在线段树上维护最大值和最小值,每次递归更新的时候,如果不能完全覆盖就暴力递归下去.挺好写的欸 ...

  2. 2018.07.27 bzoj4695: 最假女选手(线段树)

    传送门 线段树好题 支持区间加,区间取min" role="presentation" style="position: relative;"> ...

  3. [BZOJ4695]最假女选手:segment tree beats!

    分析 segment tree beats!模板题. 看了gxz的博客突然发现自己写的mxbt和mnbt两个标记没用诶. 代码 #include <bits/stdc++.h> #defi ...

  4. bzoj4695 最假女选手(势能线段树/吉司机线段树)题解

    题意: 已知\(n\)个数字,进行以下操作: \(1.\)给一个区间\([L,R]\) 加上一个数\(x\) \(2.\)把一个区间\([L,R]\) 里小于\(x\) 的数变成\(x\) \(3.\ ...

  5. bzoj 4695 最假女选手 吉利线段树

    最假女选手 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 480  Solved: 118[Submit][Status][Discuss] Desc ...

  6. 【bzoj4695】最假女选手 线段树区间最值操作

    题目描述 给定一个长度为 N 序列,编号从 1 到 N .要求支持下面几种操作:1.给一个区间[L,R] 加上一个数x 2.把一个区间[L,R] 里小于x 的数变成x 3.把一个区间[L,R] 里大于 ...

  7. 【bzoj4695】最假女选手

    zcy的励志故事.jpg 傻逼zcy突然想立一个flag,写一个segment-tree-beats的题娱乐一下 于是他就想起了这道题. 他打算今晚写完 然后光是写他就写的头昏脑涨,还犯了询问写反这种 ...

  8. BZOJ4695:最假女选手

    浅谈区间最值操作和历史最值问题:https://www.cnblogs.com/AKMer/p/10225100.html 题目传送门:https://lydsy.com/JudgeOnline/pr ...

  9. (WC2016模拟十一)【BZOJ4695】最假女选手

    ps:好久没更博啦……这几天连着有模拟赛,等初赛前后休息的时候来疯狂补坑吧……顺便补一下前面的数论啥的? 题解: mdzz我场上写了个15分暴力长度跟标算差不多... 线段树大法好啊!这题听说很多人做 ...

随机推荐

  1. WPF+数据库+三层

    1.计算类 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespac ...

  2. 搭建github

    http://www.cnblogs.com/liuxianan/p/build-blog-website-by-hexo-github.html

  3. 关于char, wchar_t, TCHAR, _T(),L,宏 _T、TEXT,_TEXT、L

    char :单字节变量类型,最多表示256个字符, wchar_t :宽字节变量类型,用于表示Unicode字符, 它实际定义在<string.h>里:typedef unsigned s ...

  4. 转 Redis集群技术及Codis实践

    转  Redis集群技术及Codis实践 转自 :http://blog.51cto.com/navyaijm/1637688 codis开源地址:https://github.com/CodisLa ...

  5. IE BHO的IObjectWithSite接口

    Internet Explorer的BHO的对象必须实现IObjectWithSite接口.该接口是IE用来对插件进行管理和通讯的一个接口,其有SetSite和GetSite两个方法,当IE加载和卸载 ...

  6. 【python】 requirements使用方法

    记得导入导出包的时候要想激活虚拟环境.1.导出requirements方法pip freeze > requirements.txt 2.安装requirements方法pip install ...

  7. C++面向对象编程,继承,数据抽象,动态绑定

    派生类(derived class)能够继承基类(base class )定义的成员: 1).派生类可以无需改变而使用那些与派生类具体特性不相关的操作 2).可以重新定义那些与派生类相关的成员函数,将 ...

  8. 响应式布局(rem布局),使用JS动态设置fontsize

    var cw = document.documentElement.clientWidth; if (cw > 1920) { cw = 1920; } document.getElements ...

  9. JavaScript词法分析解析

    函数在调用之前,会进行词法分析或者叫语法分析: 1. 函数在形成调用的那一瞬间,会有一个活动对象叫 active object ,简称AO,会分析如下几条: 形式参数 函数内局部变量声明 函数声明表达 ...

  10. [NOI2001]炮兵阵地 状压DP

    题面: 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图.在每一格平原地形上最多 ...