---
# System prepended metadata

title: '[solution] 2021-2022 ACM-ICPC Brazil Subregional Programming Contest'
tags: [題解]

---

# [solution] 2021-2022 ACM-ICPC Brazil Subregional Programming Contest

[TOC]

## pA
https://codeforces.com/gym/103388/problem/A
### 題意
給定有兩個正整數 $n$、$R$，以及 $n$ 個數值 $p_i$。

代表有 $n$ 個人，第 $i$ 個人排名第 $i$（排名約低代表越好），要給所有人禮物，但是第 $i$ 個人**至少**要給 $p_i$ 個，而且排名比較好的人不能拿的比排名較差的人還要少的禮物，最多給 $R$ 個。

問有多少種分配的方法數，$\bmod 10^9+7$。

### 測資範圍限制
- $1 \le n \le 5000$
- $1 \le R \le 10^9$
- $1 \le p_i \le 10^9$

### 解法
顯然的，若有 $p_i>R$，則答案為 $0$。

「因為排名比好的人不能拿的比排名較差的人還要少的禮物」，首先我們對 $p$ 反轉，再取前綴 $\max$，最後補上 $R$，這方便我們之後的操作。

:::info
範例

舉例來說：
$$
\begin{aligned}
p
&= [4, 8, 7, 6, 3]\\
&\Rightarrow [3, 6, 7, 8, 4] &\text{反轉整個陣列}\\
&\Rightarrow [3, 6, 7, 8, 8] &\text{取前綴 }\max \\
&\Rightarrow [3, 6, 7, 8, 8, 10] &\text{補上 }R \\
\end{aligned}
$$

待會都會用這個陣列舉例。
:::

### 重新建模

我們現在將整道題目建模成另外一道題目：
![image](https://hackmd.io/_uploads/SyZ-zXeUke.png =50%x)

從起點開始，只能往右邊或往上走，且不能走到灰色區域，問走到終點的方法數。

也就是說第 $i$ 的行，必須最少要走道 $p_i$。
> 我懶得寫灰色區域的定義，可以自己感受一下，反正跟上面的 $p$ 是相關的。


巧妙的是，因為有了灰色區域的限制，因此每一個走法中，對於每個 $x=i$，他最高的 $y$ 就是 $i$ 被分配到的禮物。

![image](https://hackmd.io/_uploads/By4a77lL1e.png =50%x)

現在最大的問題就是要怎麼算這道問題的方法數，雖然可以用 dp 計算，舉體的轉移類似 $dp[i][j] = dp[i-1][j]+dp[i][j-1]$ 的算法算，但是可以發現 $p_i$ 跟 $R$ 都很大，根本無法這樣做。

---

### 引入多項式

實際上，上面的這個 dp 想法是好的，讓我們看看在上面的圖做 dp 的效果。

![image](https://hackmd.io/_uploads/BkjYBQlIyg.png =50%x)

若我們從左到右一行一行看 dp 值，可以發現到後一行就是前一行的前綴和（要把跑到灰色區域的 dp 值刪除）。

現在要引入一些多項式的操作，我們讓每一行都可以用一個多項式表達，第 $i$ 行得到的多項式 $f_i(x)$，代入 $j$ 就會得到第 $i$ 行第 $j$ 列的值。

顯然的第 1 行是一個零次多項式，因為後面的行都是前面一行的前綴和，所以會是前面一行的最高項 $+1$ 次多項式（也就是說從左到右依序是 $0, 1, 2, \ldots n$）次多項式。

拉格朗日差值法讓我們知道，給定 $N$ 個取樣點，就可以計算代表這些取樣點的多項式代入 $k$ 的值。現在我們的目標就是從我們知道的初始多項式，推到最後的 $n$ 次多項式，並計算 $f_n(R)$ 的值，就是答案了！

:::info
拉格朗日插值法

若給定 $n+1$ 個連續的 $x$ 的取樣點，則可以在 $O(n)$ 的時間計算 $k$ 在這 $n+1$ 個取樣點代表的 $n$ 次多項式代入的值。

這個的作法可以請讀者自己去搜尋。
:::

我們不妨直接在最一開始就取 $n+1$ 個取樣點，但這 $n+1$ 個取樣點要怎麼取比較好呢？會不會跑到灰色區域？下一章節將對這些問題做補充。

---

### 選擇取樣點

首先我們會將第 1 行的取樣點推到第 2 行，並重複直到第 n 行。

並且選哪些數當取樣點根本不會影響答案（但是要是連續的，因為複雜度要求）！因此我們可以挑一些 $x$ 很大的點當取樣點，這樣它們就不會跑到灰色區域。假設我們一開始取的點 $x$ 座標在 $[10^9, 10^9+n]$。

但是選擇那麼大的 $x$ 座標就會讓我們很難從第 $i$ 行推到第 $i+1$ 行，因為要計算第 $i+1$ 座標那麼高的取樣點，就要對整行做前綴和，這樣的時間複雜度無法接受。

用一張圖代表我們現在有的資訊：
![image](https://hackmd.io/_uploads/HJxch9WLke.png)

其實不只這樣，我們還知道第 $i+1$ 行第 $p_{i}$ 列的值，因為他根本就跟第 $i$ 行第 $p_{i}$ 列的值一樣。

---
---
---
---
---
---
---
---
---

## pB
https://codeforces.com/gym/103388/problem/B

### 題意
給定一個字串長度為 $N$ 的字串 $S$，跟 $M$ 個字串 $T_i$。


對於 $S$ 的每一種旋轉 $R_1, R_2, \ldots, R_N$，設 $V_i$ 為 $\max\limits_{j \in [1, M]} lcs(R_i , T_j )$，其中 lcs 是 longest common substring 的意思。

目標求 $\min\limits_{i \in [1, N]} V_i$。

### 題目範圍限制
- $1 \le N \le 10^5$
- $1 \le M \le 10^4$
- $\sum\limits_{j \in [1, M]} |T_j| \le 10^5$

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

> 防爆雷

## 解法
先來想想要如何算出一個 $val_i$，我們可以令 $S = R_i+'\%'+T_1+'\%'+T_2+\ldots+T_M$ 塞入 Suffix Array，用 [這題](https://codeforces.com/edu/course/2/lesson/2/5/practice/contest/269656/problem/B) 的作法。

但這樣就需要 $O(N |S| \log |S|)$，顯然不夠快。

---

題目要求旋轉字串，不難想到將字串串成兩份相接的技巧，令 $P = S+S$。我們會希望可以一次計算所有 $V_i$。

首先，答案的值是否小於等於某個值 $x$ 具有單調性，觀察到這點之後不難想到二分搜。暫且讓我們定義 `check(mid)` 代表「是否存在一種旋轉 $R_i$，使得 $V_i$ 至多為 $mid$」

接著我們想要一次處理所有旋轉，因此可以設 $P = S+S$，這樣 $P$ 的每個長度為 $N$ 的字串都代表其中一個 $R_i$。這樣 `check(mid)` 就變成「==在 $P$ 中找到一個長度為 $N$ 的子字串，使得他對應到的 $V_i$ 至多為 $mid$==」。接下來的說明都會圍繞在這個問題上。

因為 `check(mid)` 有「至多」這個限制，因此對於所有 $1 \le i \le 2N$，我們會想知道 $P[i\ldots|P|-1]$，與所有 $T_j$ 的 LCS 最長是多少，並且這個 LCS 必須是從 $P[i]$ 作為開頭，這樣我們在選取長度為 $N$ 的子字串時，就可以避開一些不可選的字元，讓我們看下面的範例：

![image](https://hackmd.io/_uploads/Bk9QkctiJl.png)

承上文，我們要選擇一個長度為 $N$ 的子字串，那麼：
- 我們知道從 $P[1...8]$ 可以找的最大 LCS 且從 $P[1]$ 開始的長度為 $4$，但是因為 $mid = 3$，因此可知如果要選 $P[1]$ 這個字元，則不則選到 $P[4]$ 之後的字元。
- 我們知道從 $P[4...8]$ 可以找到的最大 LCS 且從 $P[4]$ 開始的長度為 $2$，也就是說如果選到 $P[6]$，那麼選到 $P[8]$ 以後的字元都是沒關係的，因為不會違反 LCS 至多是 $mid$ 的限制。

根據上面的推論，我們知道對於 $P$ 中的每個字元，我們都可以找到一個右界 $bound_i$，代表如果選了 $P[i]$ 這個字元，則只能選到 $bound_i$ 這個字元以內。

現在，我們希望找到一個長度為 $N$ 的區間 $[i, i+N-1]$，$\min\limits_{j \in [i, i+N-1]} bound_j \ge i+N-1$。這件事情可以輕鬆用 $O(n)$ 找到，就留給讀者自行思考了。

整個作為為 $O(\log n)$ 的二分搜乘上，

---
---
---
---
---
---
---
---
---

{%hackmd @temmie950807/r1KCzgjFh %}
{%hackmd @temmie950807/Prove_Style %}