萌新瞎想了很直接的 \(\Theta(nq)\)(在 \(\rm Luogu\) 上过了) 和一个 \(\Theta(n \log n +q \log^3 n)\) (在 \(\rm UOJ\) 上过了)的做法,就写篇题解吧。
在 \(\rm UOJ\) 过了的做法在 \(\rm Luogu\) 上过不去应该是因为洛谷空间开小了。
题意
给定长度为 \(n\) 的序列 \(h\),\(q\) 次询问,每次给定区间 \([l,r]\),你要在 \([l,r]\) 中选出一个位置 \(x\) 举行会议,使得 \(\sum\limits_{l \le i \le r} \max_{j \in [\min(i,x),\max(i,x)]} h_j\) 最小。
数据范围:\(1 \le n, q \le 7.5 \times 10^5\),\(1 \le h_i \le 10^9\)。
题解
首先考虑暴力怎么做:每次找到区间中的 \(\rm max\),然后枚举是把会议丢 \(\rm max\) 的左边还是丢右边即可,问题就被分成了两半。
考虑优化,先找到整个区间的最大值,然后把问题切成两半。不妨考虑左边那一半怎么做。
考虑先建出左边那半的单调栈。设栈中元素为 \(S_1,S_2,S_3,...,S_k\)。
其中 \(h_{S_i} \le h_{S_{i+1}}\),\(S_1 = l\),\(S_k = r\)。
枚举我们选择的会议处于栈中哪两个元素之间。假设设在 \([S_x,S_{x+1})\) 中。
那么:
- \([l,S_x)\) 的贡献均为 \(S_x\)。
- \([S_{x+1},r)\) 中一个元素的贡献只和该元素在栈中哪两个元素之间有关。
- 由于 \(x+1\) 是 \(x\) 后面第一个值 \(> h_x\) 的元素,因此 \([S_x,S_{x+1})\) 中元素的贡献可以预处理(找到 \((S_x,S_{x+1})\) 中的最大值,然后可以递归成形式相同的子问题)。
于是我们就会 \(\Theta(nq)\) 了。
直接写是过不去的。我们预处理出 \(fa_i\) 为 \(i\) 后第一个 \(> h_i\) 的元素。
然后从 \(l\) 开始暴力跳 \(fa\) 跳到 \(r\) 就过了。
观察我们的暴力是怎么完成的:其实是求了树上一条链的 \(\max(k_ix+b_i)\)。
于是可以树剖,转化为序列上区间 \(\max(k_ix+b_i)\)。建颗线段树,每个线段树上的节点 \([L,R]\) 维护一颗李超树即可。
为了优化复杂度,\([L,R]\) 上的李超树可以用 \([L,mid]\) 和 \((mid+1,R]\) 的李超树合并。
其实可以用 XJOI4182 的套路优化到 \(\Theta(n \log n + q \log^2 n)\),不过我懒就没写。
感觉这种思路也是可以再优化的,毕竟链上的元素是有单调性的。
祝大家学习愉快!