Codeforces Round #826 (Div. 3) 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: [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,2,3],
b=[1,1,2,3,1,3,2,2,3],
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 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≤t≤104) — the number of test cases.

Each test case consists of two lines.

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

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

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

Output
For each test case print on a separate line:

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.
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).

Example
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
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: [1]+[2,3,1]+[2,3]. The sequence b: [1,1,2,3,1,3,2,2,3].

In the second case, the sequence b could be obtained from the sequence a=[12,7,5] with the following partition: [12]+[7,5]. The sequence b: [12,1,2,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: [7,8,9,10,3]. The sequence b: [5,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.

思路

  1. 模拟
    从前往后枚举,枚举满足条件的边界,然后下一步 由边界+1进入更深一层的枚举(超时wa了)
  2. dp
    定义一个数组f[N],第i位为真 表示 i是满足条件的 段的右边界(每个段应该由 一个数字 n加n个数组成),
    n必然是边界, 则f[n]为true时答案就为yes

代码

1 .模拟代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<unordered_map>

using namespace std;

const int N = 2e5 + 5;
int b[N];
int fa[N], fb[N];//以i 往前往后 作为 标记值,的 必达到得点
int n, t;

bool check(int now) {
    if (now == n)return true;
    if (fa[now + 1] && fa[now + 1] <= n) {
        bool is = false;
        is = check(fa[now + 1]);
        if (is)
            return true;
    }
    for (int i = now + 2; i <= n; i++) {
        if (fb[i] == now + 1) {
            bool is = check(i);
            if (is)
                return true;
        }
    }
    return false;
}

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &b[i]);
            if (i + b[i] <= n)fa[i] = i + b[i];
            else fa[i] = 0;
            if (i - b[i] >= 1)fb[i] = i - b[i];
            else fb[i] = 0;
        
        }

        if (check(0))
            puts("YES");
        else
            puts("NO");
    }

    return 0;
}

2 .动态规划代码

#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
const int N=2e5+5;
int a[N];
void solve(){
    int n;
    scanf("%d",&n);
    // 定义 f[N]为满足条件的边界,且为you边界

    vector<bool>f(n+1,false);
    f[0]=true;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){
        // 作为前缀
        if(f[i-1]&&a[i]+i<=n)f[a[i]+i]=true;
        // 作为后缀
        if(i-a[i]>=1&&f[i-a[i]-1]==true)f[i]=true;
    }
    if(f[n])
        puts("YES");
    else
        puts("NO");
}
int main(){
    int t;
    cin>>t;
    while (t--){
        solve();
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值