20250224

D. 01 串

没场切的 T1。

statement

给定由 \(01\) 构成的长度为 \(n\) 的初始串 \(a_i\) 和目标串 \(b_i\),有三种操作:

  • \(0\)\(1\),代价为 \(t_0\)
  • \(1\)\(0\),代价为 \(t_1\)
  • 交换相邻位置的值,代价为 \(t_s\)

多测,\(1 \le \sum n \le 4 \times 10^6\),2000 ms。

solution

比较显然的 Observation:

  • 交换只会交换不同的数。
  • 同时对一个位置进行取反和交换不优。

考虑 dp,设 \(f(x)\) 为前 \(x\) 个完成变换的代价,\(f(0) = 0\)

  • 自己直接变,\(f(x) = f(x-1) + cost(a_x, b_x)\)\(cost(u, v)\)\(u\) 变成 \(v\) 的代价。
  • 有一段进行交换:
    • 找到最大的 \(y\) 使得 \((y, x]\)\(\sum a_i = \sum b_i\)
    • 这一段中 \(1\) 一定是朝同一个方向移动,否则可从中间某个位置断开;
    • 所以 \(f(x) = f(y) + t_s * |\sum_{y < i \le x} (a_i - b_i) \times i|\)

两种情况取 \(\min\) 即可。

代码中 pos[i] 是一个封装的平移坐标轴的数组,下标可以为负数。

\(O(n)\)

for (int i = -N; i <= N; ++i) pos[i] = -1;
pos[0] = 0;
for (int x = 1; x <= N; ++x) {
    s1[x] = s1[x - 1] + (a[x] - b[x]), s2[x] = s2[x - 1] + (a[x] - b[x]) * x;
    f[x] = f[x - 1] + cost(a[x], b[x]);
    int y = pos[s1[x]];
    if (~y) f[x] = min((LLL)f[x], f[y] + (LLL)CS * abs(s2[x] - s2[y]));
    pos[s1[x]] = x;
}

G. 小学生博弈题

水题。

statement

给定一个 \(n \times n\) 的方阵,第 \(i\) 行的 \([L_i, R_i]\) 内为 \(1\),其他位置为 \(0\)。求它的行列式。

多测,\(1 \le \sum n \le 1.5 \times 10^6\),1000 ms。

solution

使用左偏树模拟高斯消元即可,记录节点对应的行号和行号对应的节点,方便维护符号。

\(O(n \log n)\)

QOJ 2812 Paths

水题。

statement

给定一棵 \(n\) 个点的树,边带权。对于每个 \(x \in [1, n]\),选 \(k\) 个节点,使得 \(x\) 到这 \(k\) 个关键节点的路径交最长。\(k\) 为给定常数。

\(1 \le n \le 10^5\),300 ms。

solution

显然长剖取前 \(k\) 长链。

换根时,把父亲连儿子的边的权值,从儿子的长链中减掉,加到父亲连向当前儿子之外的最长链上。

\(k\) 大使用对顶堆维护即可。

\(O(n \log n)\)

B. 小 ds,确信

数据结构:线段树

problem

给定四个长度为 \(n\) 的序列 \(a_i\)\(b_i\)\(c_i\)\(d_i\)

\(U = \{1, 2, 3, \dots, n\}\) 划分成两个非空子集 \(S\)\(T\),最小化:

\[\max_{x \in S}\{a_x\} + \max_{x \in S}\{b_x\} + \max_{y \in T}\{c_y\} + \max_{y \in T}\{d_y\} \]

多测,\(1 \le \sum n \le 10^6\),1500 ms。

solution

考虑扫描线,钦定前两个,维护后两个,在此过程中寻找最小值。

具体地,从大到小枚举 \(\max a_x\),线段树上每个节点维护 \(\max b_x = i\)\(\max b_x + \max c_y + \max d_y\) 的值,维护区间最小值。

将一个元素由 \(S\) 移动到 \(T\) 时,因为 \(c\)\(d\) 要对当前值取 \(\max\),由于单调性,恰有一段后缀需要区间推平,使用线段树二分找到开始的位置。

要求非空子集,可以再开一棵线段树,维护当前已经确定的 \(\max a_x\) 下,合法的 \(\max b_x\) 位置,容易发现这是一个区间,线段树二分即可。

\(O(n \log n)\)

SPOJ MUZIDA - Muzidabutur

非常好线性代数。

statement

给定一个长度为 \(n\) 的序列 \(a_i\),且 \(\forall 1 \le i \le n, 0 \le a_i \le 25\)

\(q\) 组询问,每次给定 \(l\)\(r\),求区间 \([l, r]\) 本质不同子序列。答案对 \(10^9+7\) 取模。

\(1 \le n, q \le 10^6\),1000 ms。

solution

有个显然的 DP:

\(f(i, j)\) 为前 \(i\) 个数构成以 \(j\) 结尾的子序列方案数。

\[f(i, j) = \begin{cases} \sum_{0 \le k \le 25} f(i-1, j) + 1 & a_i = j \\ f(i-1, j) & a_i \neq j \end{cases}\]

直接建线段树暴力矩阵乘法是 \(O(nm^3+qm^2\log n)\) 的。

可以多加入一行列表示当前所有的和,那么对这个矩阵减去单位矩阵之后只有 \(6\) 个位置非 \(0\)

拿这几个位置进行矩阵乘法单次乘法为 \(O(m)\)\(m\) 为字符集大小)。

满秩可逆,于是可以用前 \(l-1\) 的逆乘上前 \(r\) 的矩阵,然后常数对应的行 \(sum\) 对应的列上的数即为所求。

逆矩阵乘起来的时候可以转置一下。

因为只关心“常数对应的行 \(sum\) 对应的列上的数”,所以单次询问为 \(O(m)\) 的。

\(O((n + q)m)\)


简单题结束,下面为毒瘤。

C. 形式化题面

分块

statement

一个初始为空的序列,进行 \(q\) 次操作:

  • 1 x 在末尾加入 \(x\)
  • 2 x 询问当前序列中长度为 \(x\) 的区间 价值 之和。

定义区间 \([l, r]\) 的 价值 为区间中前 \(k\) 的的数的乘积。\(k\) 为给定常数。

任意时刻序列中所有数互不相同。

强制在线,\(1 \le q \le 2 \times 10^5\)\(1 \le k \le 200\)

solution

这题有点复杂,可以分成两步。

  • 把原题转化成二维平面上的 \(O(qk)\) 次操作。
  • 使用数据结构维护各个时刻历史距离右端点距离为 \(len\) 的值。

转化

维护每个时刻 \(x\) 到当前右端点 \(n\) 的前 \(k\) 大的乘积 \(f(x)\) 以及后缀第 \(k\)\(v(x)\)(不足 \(k\) 个取最小值)。

设从 \(x\) 开始的后缀前 \(k\) 大构成的集合为 \(S(x)\)

同一时刻,显然 \(f(x)\)\(v(x)\) 非严格单调递减。

不难发现,\(S(x)\) 相同的段构成一些区间。

\(S(x) \neq S(x+1)\) 当且仅当 \(a_x \in S(x)\)。因此 \(a_x\) 被移除 \(S(x)\) 之后 \(x\) 所在的段就可以和 \(x+1\) 所在的段合并。

\(T = \{x | S(x) \neq S(x+1)\}\)。使用链表维护 \(T\)

进一步,\(|S(x) \cap S(x+1)| \ge n - 1\),一个位置只有一个数,不可能同时塞两个进去。

于是 \(S(x) \subseteq \{a_y | y \in T \land y \ge x\}\)

\(S(x)\) 要变化,当且仅当 \(a_n > v(x)\)。变化的是一段后缀。

\(n - x + 1 \le k\),则直接加入 \(S(x)\)

\(v(x) = a_x\),则本轮过后 \(x\) 应从 \(T\) 中删除。

对于最小的 \(x\) 使得 \(a_n > v(x)\)\(v(x)\) 更新为 \(\min_{y \ge x, y \in T, a_y > v(x)} \{a_y\}\)

否则令 \(y\) 为删除之前 \(x\) 的前驱。若 \(y\) 要被删除,新的 \(v(x)\) 为新的 \(v(y)\)(合并了),否则为旧的 \(v(y)\)(旧的 \(v(y)\) 也是 \([x, n-1]\) 中的第 \(k-1\) 大)。

同时维护 \(f(x)\),显然同一段的 \(f(x)\) 会增加同一个值。

考虑这样做的复杂度:若 \(a_x > a_n\),对 \(n\) 只会发生至多 \(k\) 次;若 \(a_x < a_n\),对 \(x\) 只会发生至多 \(k\) 次。操作次数均摊 \(O(qk)\)

分块维护

\(n - x\) 为横轴,\(x\) 为纵轴,建立平面直角坐标系。(修改与 \(x\) 有关,查询与 \(n - x\) 有关。)

一次修改可以看成图中的浅蓝色梯形部分,可以看成大的矩形减去黄色三角形加上粉色三角形。

询问形如如图所示的几种线段所覆盖的区域之和,且一端一定不在 \(n\) 的下面。

线段转化成点,矩形加转化成纵轴区间加一次函数。三角形加直接在横轴上加即可(之后不会访问三角形里面的点)。

使用分块平衡复杂度,\(O(1)\) 修改,\(O(\sqrt q)\) 查询。

总复杂度 \(O(q(k + \sqrt q))\)

QOJ 8366 火车旅行

https://www.cnblogs.com/SZwinsun/p/18733951

posted @ 2025-02-24 14:13  SZwinsun  阅读(24)  评论(0)    收藏  举报