#include typedef long long ll; typedef unsigned long long ull; #define FOR(i,a,b) for(int (i)=(a);i<(b);i++) #define REP(i,n) FOR(i,0,n) #define RANGE(vec) (vec).begin(),(vec).end() using namespace std; class UFTree { std::vector par_; std::vector rank_; public: UFTree(int N) { init(N); } UFTree() {} ~UFTree() {} void init(int N) { par_.resize(N); rank_.resize(N, 0); for (int i = 0; i < N; ++i) par_[i] = i; } int find(int x) { if ( par_[x] == x ) return x; else return ( par_[x] = find(par_[x])); } void unite(int x, int y) { x = find(x); y = find(y); if ( x == y ) return; if ( rank_[x] < rank_[y] ) par_[x] = y; else { par_[y] = x; if ( rank_[x] == rank_[y] ) ++rank_[x]; } } bool same(int x, int y) { return (find(x) == find(y)); } int operator[](size_t i) { return find(i); } }; class BoredomOfSavingsBox { public: void solve(void) { int N; cin>>N; // // 同時にひっくり返せるものを一つのグループとして考える。 // // 0,1,1,0,1,... // // これは適当にコインをひっくりかえすことで // // A. 1,1,1,...,1,1 // B. 1,1,1,,..,1,0 // // のどちらかのケースに帰着できる // (以下のように反転していけるから // 0,1,* -> 1,0,* // 0,0,* -> 1,1,* // 1,0,1 -> 1,1,0 // 1,0,0 -> 1,1,1 // ) // // 一度に二個のコインをひっくり返すので // 裏になっているコインの数の偶奇は変化しない。 // よって初期状態の裏のコインの数が奇数のときは全て表にはできない。 // // ただし1個だけコインをひっくり返せる場合はそれで帳尻があうので全て表にできる。 // UFTree uft(N); vector one(N,false); REP(i,N) { int d; cin>>d; int l = (1000*N+i-d)%N; int r = (d+i)%N; // 同時にひっくり返せるものを統合する uft.unite(l,r); if (l == r) one[i] = true; } // 各連結成分での偶奇チェック vector num(N,0); REP(i,N) { int w; cin>>w; num[uft[i]] += (w==0); // 裏になっているコインの数を数える // 各 one の結果を連結成分に適用 if (one[i]) one[uft[i]] = true; } // 各連結成分ごとにチェック REP(i,N) { if (uft[i] != i) // 連結成分ごとにチェック continue; if (num[uft[i]]%2 && !one[uft[i]]) { cout<<"No"<solve(); delete obj; return 0; } #endif