BZOJ4355: Play with sequence(吉司机线段树)
题意
Sol
传说中的吉司机线段树??感觉和BZOJ冒险那题差不多,就是强行剪枝。。。
这题最坑的地方在于对于操作1,$C >= 0$, 操作2中需要对0取max,$a[i] >= 0$,这不就是统计最小值出现的次数么??
按照套路
维护好区间赋值标记 / 区间加法标记 / 区间max标记 / 区间最小值 / 区间最小值出现的次数 / 区间次小值
对于第二个操作就拆成区间加 和 区间max
区间max是一个很神奇的操作
设当前加入的数为val
若val>=mn,那该操作对该区间无影响
若se < val < mn,该操作只会对次小值产生影响,因为对其他的标记均不会产生影响,因此打一个额外的标记即可
否则暴力递归
时间复杂度:$O(n log^2n)$??
另外这东西可以做区间加 / 查询历史版本,前者维护一下标记就行,,后者嘛,,,等长大了再研究吧qwq
#include<cstdio>
#include<algorithm>
#define LL long long
//#define int long long
using namespace std;
const int MAXN = * 1e5 + ;
const LL INF = 1e10 +;
inline int read() {
char c = getchar(); int x = , f = ;
while(c < '' || c > '') {if(c == '-') f = -; c = getchar();}
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x * f;
}
#define ls k << 1
#define rs k << 1 | 1
int N, Q;
int a[MAXN];
struct Node {
int l, r, siz, cnt;
LL Mx, add, mn, se, cov;
}T[MAXN << ];
void update(int k) {
//T[k].mn = min(T[ls].mn, T[rs].mn);
if(T[ls].mn < T[rs].mn) T[k].cnt = T[ls].cnt, T[k].mn = T[ls].mn, T[k].se = min(T[rs].mn, T[ls].se);
else if(T[ls].mn > T[rs].mn) T[k].cnt = T[rs].cnt, T[k].mn = T[rs].mn, T[k].se = min(T[ls].mn, T[rs].se);
else T[k].cnt = T[ls].cnt + T[rs].cnt, T[k].mn = T[ls].mn, T[k].se = min(T[ls].se, T[rs].se);
}
void MemP(int k, LL val) {
T[k].cov = val;
T[k].cnt = T[k].siz;
T[k].se = INF;
T[k].Mx = -INF;
T[k].add = ;
T[k].mn = val;
}
void AddP(int k, LL val) {
if(T[k].se != INF) T[k].se += val;
if(T[k].Mx != -INF) T[k].Mx += val;
T[k].mn += val;
T[k].add += val;
}
void MaxP(int k, LL val) {
T[k].mn = max(T[k].mn, val);//
T[k].Mx = max(T[k].Mx, val);
}
void pushdown(int k) {
if(T[k].cov != INF) MemP(ls, T[k].cov), MemP(rs, T[k].cov), T[k].cov = INF;
if(T[k].add) AddP(ls, T[k].add), AddP(rs, T[k].add), T[k].add = ;
if(T[k].Mx != -INF) MaxP(ls, T[k].Mx), MaxP(rs, T[k].Mx), T[k].Mx = -INF;
}
void Build(int k, int ll, int rr) {
T[k] = (Node) {ll, rr, rr - ll + , , -INF, , , INF, INF};
if(ll == rr) {
T[k].mn = a[ll]; T[k].cnt = ;
return ;
}
int mid = T[k].l + T[k].r >> ;
Build(ls, ll, mid); Build(rs, mid + , rr);
update(k);
}
void IntMem(int k, int ll, int rr, LL val) {
if(ll <= T[k].l && T[k].r <= rr) {MemP(k, val); return ;}
pushdown(k);
int mid = T[k].l + T[k].r >> ;
if(ll <= mid) IntMem(ls, ll, rr, val);
if(rr > mid) IntMem(rs, ll, rr, val);
update(k);
}
void IntAdd(int k, int ll, int rr, LL val) {
if(ll <= T[k].l && T[k].r <= rr) {AddP(k, val); return ;}
pushdown(k);
int mid = T[k].l + T[k].r >> ;
if(ll <= mid) IntAdd(ls, ll, rr, val);
if(rr > mid) IntAdd(rs, ll, rr, val);
update(k);
}
void IntMax(int k, int ll, int rr, LL val) {
if(val <= T[k].mn) return ;
if(ll <= T[k].l && T[k].r <= rr && T[k].se > val) {//tag
MaxP(k, val);
return ;
}
int mid = T[k].l + T[k].r >> ;
pushdown(k);
if(ll <= mid) IntMax(ls, ll, rr, val);
if(rr > mid) IntMax(rs, ll, rr, val);
update(k);
}
LL Query(int k, int ll, int rr) {
// int ans = 0;
if(ll <= T[k].l && T[k].r <= rr)
return (T[k].mn == ? T[k].cnt : );
pushdown(k);
int mid = T[k].l + T[k].r >> ;
if(ll > mid) return Query(rs, ll, rr);
else if(rr <= mid) return Query(ls, ll, rr);
else return Query(ls, ll, rr) + Query(rs, ll, rr);
}
main() {
// freopen("4355.in", "r", stdin);
// freopen("4355.out", "w", stdout);
N = read(); Q = read();
for(int i = ; i <= N; i++) a[i] = read();
Build(, , N);
while(Q--) {
int opt = read(), l = read(), r = read(), val;
if(opt == ) printf("%d\n", Query(, l, r));
else {
val = read();
if(opt == ) IntMem(, l, r, val);
else {
IntAdd(, l, r, val);
IntMax(, l, r, );
}
}
}
return ;
}
BZOJ4355: Play with sequence(吉司机线段树)的更多相关文章
- HDU - 5306 Gorgeous Sequence (吉司机线段树)
题目链接 吉司机线段树裸题... #include<bits/stdc++.h> using namespace std; typedef long long ll; ,inf=0x3f3 ...
- bzoj4355 Play with sequence(吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 赋值为\(x\) \(2.\)区间\([L,R]\) 赋值为\(max(a[i] + x, 0)\) \(3.\)区间 ...
- UVALive - 4108 SKYLINE (吉司机线段树)
题目链接 题意:在一条直线上依次建造n座建筑物,每座建筑物建造完成后询问它在多长的部分是最高的. 比较好想的方法是用线段树分别维护每个区间的最小值mi和最大值mx,当建造一座高度为x的建筑物时,若mi ...
- bzoj5312 冒险(吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)区间\([L,R]\) 按位与\(x\) \(2.\)区间\([L,R]\) 按位或\(x\) \(3.\)区间\([L,R]\) 询问最大值 ...
- bzoj4695 最假女选手(势能线段树/吉司机线段树)题解
题意: 已知\(n\)个数字,进行以下操作: \(1.\)给一个区间\([L,R]\) 加上一个数\(x\) \(2.\)把一个区间\([L,R]\) 里小于\(x\) 的数变成\(x\) \(3.\ ...
- HDU - 6315 吉司机线段树
题意:给出a,b数组,区间上两种操作,给\(a[L,R]\)+1s,或者求\(\sum_{i=l}^{r}a_i/b_i\) 一看就知道是吉司机乱搞型线段树(低配版),暴力剪枝就好 维护区间a的最大值 ...
- HDU 5306 吉司机线段树
思路: 后面nlogn的部分是伪证... 大家可以构造数据证明是这是nlog^2n的啊~ 吉老司机翻车了 //By SiriusRen #include <cstdio> #include ...
- hdu6521 吉司机线段树
http://acm.hdu.edu.cn/showproblem.php?pid=6521 待填 代码 #include<bits/stdc++.h> #define ls o<& ...
- Petrozavodsk Winter-2018. AtCoder Contest. Problem I. ADD, DIV, MAX 吉司机线段树
题意:给你一个序列,需要支持以下操作:1:区间内的所有数加上某个值.2:区间内的所有数除以某个数(向下取整).3:询问某个区间内的最大值. 思路(从未见过的套路):维护区间最大值和区间最小值,执行2操 ...
随机推荐
- SharePoint 2013 搜索高级配置
SharePoint2013里面的搜索配置. 1.首先,新建页面,用于搜索, 2.添加搜索框.搜索结果部件: 选择<搜索>类别,找到”搜索框”.”搜索结果”两个部件,添加到页面: 3.配置 ...
- [Gym 101334E]Exploring Pyramids(区间dp)
题意:给定一个先序遍历序列,问符合条件的树的种类数 解题关键:枚举分割点进行dp,若符合条件一定为回文序列,可分治做,采用记忆化搜索的方法. 转移方程:$dp[i][j] = \sum {dp[i + ...
- Flask13 面试要能吹 、安装虚拟机、虚拟机全局设置、导入虚拟机文件、虚拟机局部设置
1 web开发工作的三个能力 1.1 开发思想 易维护:开发成本远低于维护成本 可扩展:随着访问量的增加会自动使用多个数据库 高可用:程序就像小强一样,开发的系统能够经得住狂风暴雨的吹残(例如:一台主 ...
- 树莓派 Learning 002 装机后的必要操作 --- 02 解决中文问题
树莓派 装机后的必要操作 - 解决中文问题 我的树莓派型号:Raspberry Pi 2 Model B V1.1 装机系统:NOOBS v1.9.2 每一块树莓派,装机后都应该执行的步骤 刚装机后, ...
- R: vector 向量的创建、操作等。
################################################### 问题:创建.操作向量 18.4.27 怎么创建向量 vector,,及其相关操作 ??? 解 ...
- vim加亮和自动缩进
修改/etc/vimrc 添加 set cindent syntax on
- HDU 5245 Joyful (期望)
题意:进行K次染色,每次染色会随机选取一个以(x1,y1),(x2,y2)为一组对角的子矩阵进行染色,求K次染色后染色面积的期望值(四舍五入). 析:我们可以先求出每个格子的期望,然后再加起来即可.我 ...
- App集成极光推送开发流程[关键步骤]
1.客户端集成SDK 1.1初始化 JPushInterface.setDebugMode(true); // 设置开启日志,发布时请关闭日志 JPushInterface.init(this); / ...
- FormsAuthentication.RedirectFromLoginPage 登录
首先讲的这个东西是针对后台数据访问的比如我的后台是admin文件夹.那么我除非登陆成功才可以访问里面的东西.那么除了Session对象判断.和Cookies来判断还能用到FormsAuthentica ...
- jexus处理静态文件(处理后缀)
AspNet_Exts=txt就能把你指定的扩展名交给asp.net处理.同理,可以写很多个,AspNet_Exts=txt,htm,html