pSort CF28B

原题链接 位于CodeForcesicon-default.png?t=M666https://codeforces.com/problemset/problem/28/B

One day n cells of some array decided to play the following game. Initially each cell contains a number which is equal to it's ordinal number (starting from 1). Also each cell determined it's favourite number. On it's move i-th cell can exchange it's value with the value of some other j-th cell, if |i - j| = di, where di is a favourite number of i-th cell. Cells make moves in any order, the number of moves is unlimited.

The favourite number of each cell will be given to you. You will also be given a permutation of numbers from 1 to n. You are to determine whether the game could move to this state.

Input

The first line contains positive integer n (1 ≤ n ≤ 100) — the number of cells in the array. The second line contains n distinct integers from 1 to n — permutation. The last line contains n integers from 1 to n — favourite numbers of the cells.

Output

If the given state is reachable in the described game, output YES, otherwise NO.

Examples

input

5
5 4 3 2 1
1 1 1 1 1

output

YES

input

7
4 3 5 1 2 7 6
4 6 6 1 6 6 1

output

NO

input

7
4 2 5 1 3 7 6
4 6 6 1 6 6 1

output

YES

这道题需要我们用到并查集,即可以 合“并” 和”查“询 的多个集合

依照题意,数组每个位置的“favourite”就是能与其交换的数组位置,只要我们将所有能交换的数组下标放到一个连通块里,最后查询每个数组的下标与数是否都在一个连通块里就可以判断它是否能够进入自己的位置了,如果有数字不在一个连通块则输出NO

#include <stdio.h>
#include <iostream>
using namespace std;

int dsu[110]; // 并查集
int num[110];

int find(int x) // “查”
{
    return x == dsu[x] ? x : dsu[x] = find(dsu[x]);
}

void merge(int x, int y) // “并”
{
    x = find(x);
    y = find(y);
    dsu[x] = y;
}

int main()
{
    int n;
    scanf("%d", &n);

    for (int i = 1; i <=n; i++) dsu[i] = i; // 并查集初始化
    for (int i = 1; i <=n; i++) scanf("%d", &num[i]);

    int t;
    for (int i = 1; i <= n; i++)
    {
        scanf("%d", &t);
        if (i-t >= 1) merge(i, i-t);
        if (i+t <= n) merge(i, i+t);
    }

    for (int i = 1; i <= n; i++)
        if (find(i) != find(num[i])) // 查询是否在同一个连通块
        {
            printf ("NO");
            return 0;
        }
    printf ("YES");

    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值