ABC234G Divide a Sequence
题意:
给定一个长度为 \(n\) 的序列 \(A\),对于每一种把序列 \(A\) 分成 \(k\) 个子段(设为 \(B_1,B_2,\dots,B_n\))的方案(共有 \(2^{n-1}\) 种),定义其权值为 \(\prod\limits_{i=1}^k (\max(B_i)-\min(B_i))\),问所有划分权值的和 \(\mod998244353\) 的结果。
数据范围:\(1\le n\le3\times10^5\),\(1\le A_i\le10^9\)。
可以列出一个很显然的 DP:设 \(f_i\) 表示划分完前 \(i\) 个数的所有方案权值的和。
转移:\(f_i=\sum\limits_{j=0}^{i-1}(f_j\times(\max(j+1,i)-\min(j+1,i)))\)。
暴力是 \(\mathcal{O}(n^2)\) 的。
先把式子拆开, \(\max\) 和 \(\min\) 分开考虑。
观察到对于每一个左端点,对应的 \(\max\) 系数不降、\(\min\) 系数不增,于是很自然地想到单调栈。
具体地,分别维护两个递增和递减的单调栈,栈顶记录两个元素 \(\{val, sumval\}\) 分别为栈顶对应的值和 \(\sum\limits_{j<i}\) \([j\) 对应的转移系数为 \(val]\times dp_j\)。
可能有点抽象,建议画个图理解一下。
注意 \(A_i\) 的大小超过了模数,在做乘法时要先取模。
Code:https://atcoder.jp/contests/abc234/submissions/29942178。
ABC234H Enumerate Pairs
题意:
给定 \(n\) 个平面上的点 \((x_i,y_i)\) 和一个整数 \(K\),输出所有欧几里德距离 \(\le K\) 的点对。
保证点对数不超过 \(4\times10^5\)。
数据范围:\(1\le n\le2\times10^5\),\(1\le K\le1.5\times10^9\),\(0\le x_i,y_i\le10^9\)。
使用 k-D Tree 暴力做即可。
注意直接把子树内节点的所有坐标信息存下来并不会爆空间,因为按照方差建树的 k-D Tree 树高是 \(\mathcal{O}(\log n)\) 的。
当然最稳妥的方式还是直接剪枝,即 在到这个点控制的矩形的最小距离 \(>K\) 的时候直接返回 和 在到这个点的最大距离 \(\le K\) 的时候加入这个子树内的所有点。
Code1:https://atcoder.jp/contests/abc234/submissions/29939069。
Code2:https://atcoder.jp/contests/abc234/submissions/29940278。