E. Sending a Sequence Over the Network
E. Sending a Sequence Over the Network
The sequence $a$ is sent over the network as follows:
- sequence $a$ is split into segments (each element of the sequence belongs to exactly one segment, each segment is $a$ group of consecutive elements of sequence);
- for each segment, its length is written next to it, either to the left of it or to the right of it;
- the resulting sequence $b$ is sent over the network.
For example, we needed to send the sequence $a=[1,2,3,1,2,3]$. Suppose it was split into segments as follows: $[{\color{Red} 1}]+[{\color{Blue} {2,3,1}}]+[{\color{Green} {2,3}}]$. Then we could have the following sequences:
- $b=[1,{\color{Red}1},3,{\color{Blue}{2,3,1}},{\color{Green}{2,3}},2]$,
- $b=[{\color{Red}1},1,3,{\color{Blue}{2,3,1}},2,{\color{Green}{2,3}}]$,
- $b=[{\color{Red}1},1,{\color{Blue}{2,3,1}},3,2,{\color{Green}{2,3}}]$,
- $b=[{\color{Red}1},1,{\color{Blue}{2,3,1}},3,{\color{Green}{2,3}},2]$.
If a different segmentation had been used, the sent sequence might have been different.
The sequence $b$ is given. Could the sequence $b$ be sent over the network? In other words, is there such a sequence $a$ that converting $a$ to send it over the network could result in $a$ sequence $b$?
Input
The first line of input data contains a single integer $t (1 \leq t \leq {10}^{4})$ — the number of test cases.
Each test case consists of two lines.
The first line of the test case contains an integer $n (1 \leq n \leq 2 \times {10}^{5})$ — the size of the sequence $b$.
The second line of test case contains $n$ integers $b_1,b_2, \dots ,b_n (1 \leq b_i \leq {10}^{9})$ — the sequence $b$ itself.
It is guaranteed that the sum of $n$ over all test cases does not exceed $2 \cdot {10}^{5}$.
Output
For each test case print on a separate line:
- $\text{YES}$ if sequence $b$ could be sent over the network, that is, if sequence $b$ could be obtained from some sequence $a$ to send $a$ over the network.
- $\text{NO}$ otherwise.
You can output $\text{YES}$ and $\text{NO}$ in any case (for example, strings $\text{yEs}$, $\text{yes}$, $\text{Yes}$ and $\text{YES}$ will be recognized as positive response).
Example
input
7 9 1 1 2 3 1 3 2 2 3 5 12 1 2 7 5 6 5 7 8 9 10 3 4 4 8 6 2 2 3 1 10 4 6 2 1 9 4 9 3 4 2 1 1
output
YES
YES
YES
NO
YES
YES
NO
Note
In the first case, the sequence $b$ could be obtained from the sequence $a=[1,2,3,1,2,3]$ with the following partition: $[{\color{Red} 1}]+[{\color{Blue} {2,3,1}}]+[{\color{Green} {2,3}}]$. The sequence $b$: $[{\color{Red} 1},1,{\color{Blue} {2,3,1}},3,2,{\color{Green} {2,3}}]$.
In the second case, the sequence $b$ could be obtained from the sequence $a=[12,7,5]$ with the following partition: $[{\color{Red} {12}}]+[{\color{Green} {7,5}}]$. The sequence $b$: $[{\color{Red} {12}},1,2,{\color{Green} {7,5}}]$.
In the third case, the sequence $b$ could be obtained from the sequence $a=[7,8,9,10,3]$ with the following partition: $[{\color{Red} {7,8,9,10,3}}]$. The sequence $b$: $[5,{\color{Red} {7,8,9,10,3}}]$.
In the fourth case, there is no sequence $a$ such that changing a for transmission over the network could produce a sequence $b$.
解题思路
写这题的时候完全没想到是动态规划。
定义状态$f(i)$表示所有以$i$为结尾的前缀合法方案的集合,如果存在合法方案的话那么$f(i) = true$,否则$f(i) = false$。
考虑每一个位置$i$作为信息码的情况,如果下标$i$作为信息段的右端点,且$i - a_i \geq 1$,意味着区间$[i - a_i, i]$可以作为一段合法的信息,此时如果要保证以$i$为结尾的前缀存在合法方案,就要看看以$i - a_i - 1$为结尾的前缀是否存在合法方案,这个值就是$f(i - a_i - 1)$,因此$f(i) ~|= f(i - a_i - 1)$。同理,再考虑$i$作为信息段树的左端点,如果$i + a_i \leq n$,意味着区间$[i, i + a_i]$可以作为一段合法的信息,此时如果要保证以$i + a_i$为结尾的前缀存在合法方案,就要看看以$i - 1$为结尾的前缀是否存在合法方案,这个值就是$f(i - 1)$,因此$f(i + a_i) ~|= f(i - 1)$。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 2e5 + 10; 5 6 int a[N]; 7 bool f[N]; 8 9 void solve() { 10 int n; 11 scanf("%d", &n); 12 for (int i = 1; i <= n; i++) { 13 scanf("%d", a + i); 14 } 15 memset(f, 0, sizeof(f)); 16 f[0] = true; 17 for (int i = 1; i <= n; i++) { 18 if (i - a[i] - 1 >= 0) f[i] |= f[i - a[i] - 1]; 19 if (i + a[i] <= n) f[i + a[i]] |= f[i - 1]; 20 } 21 printf("%s\n", f[n] ? "YES" : "NO"); 22 } 23 24 int main() { 25 int t; 26 scanf("%d", &t); 27 while (t--) { 28 solve(); 29 } 30 31 return 0; 32 }
参考资料
Codeforces Round #826 (Div. 3) Editorial:https://codeforces.com/blog/entry/107908
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16786198.html