(cf)Codeforces Round #826 (Div. 3)E题解. Sending a Sequence Over the Network

E题算是一个比较经典的dp吧,有一点思维,调了半个小时差不多。

如果是正常的cf比赛的话,我应该做不到这个题,因为做题速度太慢了。

The sequence aa is sent over the network as follows:

  1. sequence aa is split into segments (each element of the sequence belongs to exactly one segment, each segment is a group of consecutive elements of sequence);
  2. for each segment, its length is written next to it, either to the left of it or to the right of it;
  3. the resulting sequence bb is sent over the network.

For example, we needed to send the sequence a=[1,2,3,1,2,3]a=[1,2,3,1,2,3]. Suppose it was split into segments as follows: [1]+[2,3,1]+[2,3][1]+[2,3,1]+[2,3]. Then we could have the following sequences:

  • b=[1,1,3,2,3,1,2,3,2]b=[1,1,3,2,3,1,2,3,2],
  • b=[1,1,3,2,3,1,2,2,3]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,2,3],
  • b=[1,1,2,3,1,3,2,3,2]b=[1,1,2,3,1,3,2,3,2].

If a different segmentation had been used, the sent sequence might have been different.

The sequence bb is given. Could the sequence bb be sent over the network? In other words, is there such a sequence aa that converting aa to send it over the network could result in a sequence bb?

Input

The first line of input data contains a single integer tt (1≤t≤1041≤t≤104) — the number of test cases.

Each test case consists of two lines.

The first line of the test case contains an integer nn (1≤n≤2⋅1051≤n≤2⋅105) — the size of the sequence bb.

The second line of test case contains nn integers b1,b2,…,bnb1,b2,…,bn (1≤bi≤1091≤bi≤109) — the sequence bb itself.

It is guaranteed that the sum of nn over all test cases does not exceed 2⋅1052⋅105.

Output

For each test case print on a separate line:

  • YES if sequence bb could be sent over the network, that is, if sequence bb could be obtained from some sequence aa to send aa over the network.
  • NO otherwise.

You can output YES and NO in any case (for example, strings yEs, yes, Yes and YES will be recognized as positive response).

题意:把一个序列分成多个连续的子序列,每个子序列都有一个长度值,这个值可能在它的左边,也可能在他的右边,问给你一个最终序列,问你它是不是由一个原序列变化来的。

很容易就想到dp,我们来枚举每个数如果是长度值的情况,用一个dis数组来记录,到第i个点的最长覆盖了数组中多少个元素。

然后枚举每个数如果是左边序列的长度值,和是右边序列的长度值的情况。

最后编列整个dis数组,如果里面有值等于n的话,那就说明可以全部覆盖,输出yes,否则就输出no。

#include 
using namespace std;
typedef long long int LL;
const int N=200010;
LL a[N];
LL dis[N];
LL f[N][3];//其实不用数组也可以,这里可以优化一下空间。
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%lld",&a[i]);
		}
		for(int i=1;i<=n;i++)//注意这里千万不能用memset,否则必超时,因为t的数量太大了。
		{
			f[i][0]=0;
			f[i][1]=0;
			dis[i]=0;
		}
		for(int i=1;i<=n;i++)
		{
			if(i-a[i]>=1)//向左的情况,判断越界
			{
				f[i][0]=max(f[i][0],dis[i-a[i]-1]+a[i]+1);
				dis[i]=max(dis[i],f[i][0]);
			}
			if(i+a[i]<=n)//向右的情况,判断越界
			{
				f[i][1]=max(f[i][1],dis[i-1]+a[i]+1);
				dis[i+a[i]]=max(dis[i+a[i]],f[i][1]);
			}
		}
		int j;
		for(j=1;j<=n;j++)
		{
			if(dis[j]==n)
			break;
		}
		if(j<=n)
		printf("YES\n");
		else printf("NO\n");
		
	}
	return 0;
}

你可能感兴趣的:(codeforces,算法,数据结构)