E. Sending a Sequence Over the Network(DP)

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值