Loading

IOI2018 meetings

萌新瞎想了很直接的 \(\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})\) 中。

那么:

  1. \([l,S_x)\) 的贡献均为 \(S_x\)
  2. \([S_{x+1},r)\) 中一个元素的贡献只和该元素在栈中哪两个元素之间有关。
  3. 由于 \(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\) 就过了。

\(n^2\) 过百万,暴力碾标算!

观察我们的暴力是怎么完成的:其实是求了树上一条链的 \(\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)\),不过我懒就没写

aclink

感觉这种思路也是可以再优化的,毕竟链上的元素是有单调性的。

祝大家学习愉快!

posted @ 2021-12-09 13:31  zhoukangyang  阅读(684)  评论(0编辑  收藏  举报