Problem - 1741E - Codeforces
序列a在网络上的发送情况如下。
序列a被分割成若干段(序列的每个元素正好属于一个段,每个段是序列的一组连续元素)。
对于每个段,它的长度被写在它的旁边,要么在它的左边,要么在它的右边。
得到的序列b被发送到网络上。
例如,我们需要发送序列a=[1,2,3,1,2,3]。假设它被分割成如下的片段。[1]+[2,3,1]+[2,3]. 那么我们可以有以下的序列。
b=[1,1,3,2,3,1,2,3,2],
b=[1,1,3,2,3,1,2,2,3],
b=[1,1,2,3,1,3,2,2,3],
b=[1,1,2,3,1,3,2,3,2].
如果使用了不同的分割,发送的序列可能会有所不同。
序列b是给定的。序列b可以通过网络发送吗?换句话说,是否有这样一个序列a,将a转换为网络上的发送序列b?
输入
输入数据的第一行包含一个整数t(1≤t≤104)--测试案例的数量。
每个测试用例由两行组成。
测试用例的第一行包含一个整数n(1≤n≤2⋅105)--序列b的大小。
测试用例的第二行包含n个整数b1,b2,...,bn(1≤bi≤109)--序列b本身。
可以保证所有测试用例的n之和不超过2⋅105。
输出
对于每个测试用例,在单独一行中打印。
如果序列b可以通过网络发送,也就是说,如果序列b可以从某个序列a中得到,以便通过网络发送a,则为YES。
否则为NO。
你可以在任何情况下输出YES和NO(例如,字符串yEs、yes、Yes和YES将被识别为积极响应)。
inputCopy
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
outputCopy
是
是的
是
没有
是
是
无
备注
在第一种情况下,序列b可以从序列a=[1,2,3,1,2,3]中得到,分区如下。[1]+[2,3,1]+[2,3]. 序列b:[1,1,2,3,1,3,2,2,3]。
在第二种情况下,序列b可以从序列a=[12,7,5]中得到,其分割方式如下。[12]+[7,5]. 序列b:[12,1,2,7,5]。
在第三种情况下,序列b可以从序列a=[7,8,9,10,3]中得到,分区如下。[7,8,9,10,3]. 序列b:[5,7,8,9,10,3]。
在第四种情况下,不存在序列a,以至于改变a在网络上的传输可以产生序列b。
题解:
每一次判断当前位置是否合法,都要从前面转移过来
假如说,当前位置为i,
i-a[i]-1 >= 0边界限制
f[i-a[i]-1]如果合法
根据题意,那么i-a[i] ~ i一定是合法的,
否则既然前面都已经不合法了,后面就一定不合法
对后面元素也要判断,
还是先判断边界
i + a[i+1]+1<=n
f[i]也应是合法的情况下才能进行下面的
f[i+a[i+1]+1] = 1也一定合法
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define int long long
//1 1 3 3 3
int a[300050];
int f[300050];
void solve()
{
int n;
cin >> n;
for(int i = 1;i <= n;i++)
cin >> a[i],f[i] = 0;
f[0] = 1;
for(int i = 0;i <= n;i++)
{
if(i-a[i] -1>=0&&f[i - a[i]-1])
f[i] = 1;
if(f[i]&&i+a[i+1]+1<=n)
f[i+a[i+1]+1] = 1;
}
if(f[n])
cout<<"YES\n";
else
cout<<"NO\n";
}
signed main()
{
int t = 1;
cin >> t;
while(t--)
{
solve();
}
}
//2 5
//3
//9 7
//2 3 4 3