当前位置: 首页 > news >正文

2023 NOIP A层联测9 - 风信子 题解

思路

我们可以考虑设 f l 0 , r 0 , l 1 , r 1 f_{l_0,r_0,l_1,r_1} fl0,r0,l1,r1 表示最大的 a l − a r a_l-a_r alar,其中 l ∈ [ l 0 , r 0 ] l\in [l_0,r_0] l[l0,r0] r ∈ [ l 1 , r 1 ] r\in [l_1, r_1] r[l1,r1]

于是如果我们能够快速求出 f f f 值,那么我们就能解决问题。

考虑如何快速求 f f f 值。

发现似乎没有什么好方法,但是我们在某些特殊情况下是可以快速求的,即当 l 0 = l 1 l_0=l_1 l0=l1 r 0 = r 1 r_0=r_1 r0=r1 r 0 < l 1 r_0<l_1 r0<l1 时,我们可以用线段树快速求出其 f f f 值。

我们又发现刚开始给出的左右两边端点能取的区间是一样的,于是我们考虑当取出这区间的最大值之后,如何拆分区间使得拆分出来的区间满足上面的特殊情况。

l 0 = l 1 l_0=l_1 l0=l1 r 0 = r 1 r_0=r_1 r0=r1 时,我们假设此时最大值的为 a x − a y a_x - a_y axay,当我们取出 a x − a y a_x - a_y axay 后,我们就不能再取 ( x , y ) (x,y) (x,y) 这对数了,此时我们的左右端点的区间会改变,于是我们可以将改变后的区间拆为如下六种形式。

  • 左端点 ∈ [ l , x − 1 ] \in [l, x - 1] [l,x1],右端点 ∈ [ l , x − 1 ] \in[l, x - 1] [l,x1],此时 x > l x > l x>l
  • 左端点 ∈ [ l , x − 1 ] \in [l, x - 1] [l,x1],右端点 ∈ [ x , r ] \in[x, r] [x,r],此时 x > l x > l x>l
  • 左端点 ∈ [ x , x ] \in [x, x] [x,x],右端点 ∈ [ x , x ] \in[x, x] [x,x],此时 x ≠ y x \not = y x=y
  • 左端点 ∈ [ x , x ] \in [x, x] [x,x],右端点 ∈ [ x + 1 , y − 1 ] \in[x + 1, y - 1] [x+1,y1],此时 x < y − 1 x < y - 1 x<y1
  • 左端点 ∈ [ x , x ] \in [x, x] [x,x],右端点 ∈ [ y + 1 , r ] \in[y + 1, r] [y+1,r],此时 y > r y > r y>r
  • 左端点 ∈ [ x + 1 , r ] \in [x + 1,r] [x+1,r],右端点 ∈ [ x + 1 , r ] \in[x + 1, r] [x+1,r],此时 x < r x < r x<r

因为此时 l 0 = l 1 l_0 = l_1 l0=l1 r 0 = r 1 r_0 = r_1 r0=r1,所以我们用 l l l r r r 代替。

注意一下后面的条件,要满足其这个取值区间才会存在。

还有一种情况为 r 0 < l 1 r_0<l_1 r0<l1,此时拆分形式如下。

  • 左端点 ∈ [ l 0 , x − 1 ] \in [l_0, x - 1] [l0,x1],右端点 ∈ [ l 1 , r 1 ] \in[l_1, r_1] [l1,r1],此时 l 0 < x l_0 < x l0<x
  • 左端点 ∈ [ x , x ] \in [x, x] [x,x],右端点 ∈ [ l 1 , y − 1 ] \in[l_1, y - 1] [l1,y1],此时 l 1 < y l_1 < y l1<y
  • 左端点 ∈ [ x , x ] \in [x, x] [x,x],右端点 ∈ [ y + 1 , r 1 ] \in[y + 1, r_1] [y+1,r1],此时 y < r 1 y < r_1 y<r1
  • 左端点 ∈ [ x + 1 , r 0 ] \in [x + 1, r_0] [x+1,r0],右端点 ∈ [ l 1 , r 1 ] \in[l_1, r_1] [l1,r1],此时 x < r 0 x < r_0 x<r0

于是我们发现,当我们满足特殊条件时的区间,取出最大值后还是能变成满足特殊条件的区间,于是我们就可以做出来了。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL inf = 1e16;
int n, Q, a[100005];
LL bz[5000005];
struct Grid {LL val; int id;friend bool operator> (Grid a, Grid b) { return a.val > b.val; }friend bool operator< (Grid a, Grid b) { return a.val < b.val; }
} maxn[5000005], minn[5000005];
struct Ans {LL val; int x, y;friend bool operator> (Ans a, Ans b) { return a.val > b.val; }friend bool operator< (Ans a, Ans b) { return a.val < b.val; }
} ans[5000005];
inline void updata(int x) {maxn[x] = max(maxn[x * 2], maxn[x * 2 + 1]);minn[x] = min(minn[x * 2], minn[x * 2 + 1]);ans[x] = max(ans[x * 2], ans[x * 2 + 1]);if (maxn[x * 2].val - minn[x * 2 + 1].val > ans[x].val)ans[x].val = maxn[x * 2].val - minn[x * 2 + 1].val, ans[x].x = maxn[x * 2].id, ans[x].y = minn[x * 2 + 1].id;
}
inline void build(int x, int l, int r) {if (l == r) {maxn[x].val = minn[x].val = a[l], ans[x].val = 0;maxn[x].id = minn[x].id = ans[x].x = ans[x].y = l;return ;}int mid = l + r >> 1;build(x * 2, l, mid), build(x * 2 + 1, mid + 1, r);updata(x);
}
inline void pushdown(int x) {maxn[x].val += bz[x], minn[x].val += bz[x];bz[x * 2] += bz[x], bz[x * 2 + 1] += bz[x];bz[x] = 0;
}
inline void add(int x, int l, int r, int sl, int sr, int val) {pushdown(x);if (r < sl || sr < l)return ;if (sl <= l && r <= sr) {bz[x] += val;pushdown(x);return ;}int mid = l + r >> 1;add(x * 2, l, mid, sl, sr, val), add(x * 2 + 1, mid + 1, r, sl, sr, val);updata(x);
}
inline Grid find_max(int x, int l, int r, int sl, int sr) {pushdown(x);if (r < sl || sr < l)return { -inf, 0 };if (sl <= l && r <= sr)return maxn[x];int mid = l + r >> 1;return max(find_max(x * 2, l, mid, sl, sr), find_max(x * 2 + 1, mid + 1, r, sl, sr));
}
inline Grid find_min(int x, int l, int r, int sl, int sr) {pushdown(x);if (r < sl || sr < l)return { inf, 0 };if (sl <= l && r <= sr)return minn[x];int mid = l + r >> 1;return min(find_min(x * 2, l, mid, sl, sr), find_min(x * 2 + 1, mid + 1, r, sl, sr));
}
inline Ans find_ans(int x, int l, int r, int sl, int sr) {pushdown(x);if (r < sl || sr < l)return { -inf, 0, 0 };if (sl <= l && r <= sr)return ans[x];int mid = l + r >> 1;Ans t = max(find_ans(x * 2, l, mid, sl, sr), find_ans(x * 2 + 1, mid + 1, r, sl, sr));Grid a = find_max(x * 2, l, mid, sl, sr), b = find_min(x * 2 + 1, mid + 1, r, sl, sr);t = max(t, {a.val - b.val, a.id, b.id});return t;
}
struct node {int il, ir, jl, jr;LL val;Ans Val() {if (ir < jl) {Grid l = find_max(1, 1, n, il, ir), r = find_min(1, 1, n, jl, jr);return { l.val - r.val, l.id, r.id };}elsereturn find_ans(1, 1, n, il, ir);}friend bool operator< (node a, node b) { return a.val < b.val; }
} ;
priority_queue <node> q;
int main() {scanf("%d%d", &n, &Q);for (int i = 1; i <= n; i++)scanf("%d", &a[i]);build(1, 1, n);while (Q--) {int opt, L, R, k;scanf("%d%d%d%d", &opt, &L, &R, &k);if (opt == 1)add(1, 1, n, L, R, k);else {node t;t.il = t.jl = L, t.jr = t.ir = R;t.val = t.Val().val;q.push(t);LL sum = 0;while (k) {node now = q.top();Ans val = now.Val();int x = val.x, y = val.y;q.pop(), k--;sum = sum + val.val;if (now.ir < now.jl) {if (x > now.il) {t.il = now.il, t.ir = x - 1, t.jl = now.jl, t.jr = now.jr;t.val = t.Val().val;q.push(t);}if (now.jl < y) {t.il = x, t.ir = x, t.jl = now.jl, t.jr = y - 1;t.val = t.Val().val;q.push(t);}if (y < now.jr) {t.il = x, t.ir = x, t.jl = y + 1, t.jr = now.jr;t.val = t.Val().val;q.push(t);}if (x < now.ir) {t.il = x + 1, t.ir = now.ir, t.jl = now.jl, t.jr = now.jr;t.val = t.Val().val;q.push(t);}}else {int l = now.il, r = now.ir;if (x > l) {t.il = l, t.ir = x - 1, t.jl = l, t.jr = x - 1;t.val = t.Val().val;q.push(t);t.il = l, t.ir = x - 1, t.jl = x, t.jr = r;t.val = t.Val().val;q.push(t);}if (x != y) {t.il = x, t.ir = x, t.jl = x, t.jr = x;t.val = t.Val().val;q.push(t);}if (x < y - 1) {t.il = x, t.ir = x, t.jl = x + 1, t.jr = y - 1;t.val = t.Val().val;q.push(t);}if (y < r) {t.il = x, t.ir = x, t.jl = y + 1, t.jr = r;t.val = t.Val().val;q.push(t);}if (x < r) {t.il = x + 1, t.ir = r, t.jl = x + 1, t.jr = r;t.val = t.Val().val;q.push(t);}}}printf("%lld\n", sum);while (!q.empty())q.pop();}}return 0;
}
http://www.lryc.cn/news/189052.html

相关文章:

  • 岩土工程安全监测无线振弦采集仪在无线组网的关键要点
  • 代码随想录Day14 LeetCodeT110平衡二叉树 T257二叉树的所有路径 T404 左叶子之和
  • C语言自定义类型_枚举联合(3)
  • asp.net网上销售系统VS开发mysql数据库web结构c#编程Microsoft Visual Studio计算机毕业设计
  • 【Windows】RPC调用过程实例详解
  • 动手学强化学习第2章多臂老虎机
  • 钡铼BL124EC实现EtherCAT转Ethernet/IP的优势
  • 使用IntelliJ Idea必备的插件!
  • 代码随想录算法训练营第23期day19| 654.最大二叉树、617.合并二叉树、700.二叉搜索树中的搜索、98.验证二叉搜索树
  • 第四章 字符串part02 28. 实现strStr() 459. 重复的子字符串
  • 设计模式 - 状态模式
  • 【vim 学习系列文章 9 -- .vim 脚本文件开发学习】
  • NAT模式和桥接模式的区别
  • 应对出海安全合规挑战,兆珑科技为什么选择了亚马逊云科技?
  • Allegro基本规则设置指导书之Spacing规则设置
  • 使用【Blob、Base64】两种方式显示【文本、图片、视频】 使用 video 组件播放视频
  • 深度学习_1_基本语法
  • c#设计模式-行为型模式 之 中介者模式
  • 小程序uView2.X框架upload组件上传方法总结+避坑
  • 人脸检测及追踪回顾
  • 虚拟环境和包
  • springboot配置文件读取
  • 纵享丝滑!Cesium + ffmpegserver 生成高质量动态视频【逐帧生成】
  • Linux下C++编程-进度条
  • C语言常见题目(1)交换两个变量的值,数的逆序输出,猜数游戏,两个数比较大小等
  • Springboot使用sqlcipher4加密sqlite数据库
  • 指针拔尖(2)(巩固提高,全网最牛,包会,看不懂带电脑来找我)
  • 本地部署多语言代码生成模型CodeGeeX2
  • C语言刷题练习(Day2)
  • docker- harbor私有仓库部署与管理