Codeforces Beta Round #28 B 题

今天悲剧的第一题没看懂题,好吧,不会做,B 题最简单,放出来。

这题的思路实际上是并查集,先定义一个数组 stst 表示现在的状态,目标状态是 123n1,2,3,\cdots,n,那么,每次查找 iii+v[i]i+v[i] iv[i]i-v[i] 三个数,把他们合并,表示他们可以互相转换,那么用 O(n)O(n) 的复杂度扫一遍,可以把全部的元素属于什么集合预处理出来,最后只要判断 st[i]st[i]ii 是不是一个集合里的就可以了。

今天无聊复习 C++,封装了个并查集的类,刚好用上。。。

我的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <cstdio>

using namespace std;

class Set {
private:
const static int maxsize = 110000;
int p[maxsize];
int rank[maxsize];
int size;
void Link(int x, int y);
void init();

public:
Set();
Set(const int& n);
Set(Set& st);
int Find(int x);
void Union(int x, int y);
bool Same(int x, int y);
bool Union2(int x, int y);
bool IsRoot(int x);
void Reset();
void Reset(const int& n);
int Size();
};

void Set::Link(int x, int y) {
if (rank[x] > rank[y])
p[y] = x;
else {
p[x] = y;
if (rank[x] == rank[y]) rank[y]++;
}
}

int Set::Size() { return size; }

void Set::init() {
for (int i = 1; i <= size; i++) {
p[i] = i;
rank[i] = 0;
}
}

Set::Set() {
size = maxsize - 1;
init();
}

Set::Set(const int& n) {
size = n;
if (n < maxsize) init();
}

Set::Set(Set& st) {
size = st.size;
for (int i = 1; i <= size; i++) {
p[i] = st.p[i];
rank[i] = st.rank[i];
}
}

int Set::Find(int x) {
if (!IsRoot(x)) p[x] = Find(p[x]);
return p[x];
}

void Set::Union(int x, int y) {
int px = Find(x);
int py = Find(y);
if (px != py) {
Link(px, py);
}
}

bool Set::Same(int x, int y) { return Find(x) == Find(y); }

bool Set::Union2(int x, int y) {
int px = Find(x);
int py = Find(y);
if (px != py) {
Link(px, py);
return false;
} else
return true;
}

bool Set::IsRoot(int x) { return p[x] == x; }

void Set::Reset() {
size = maxsize - 1;
init();
}

void Set::Reset(const int& n) {
size = n;
if (n < maxsize) init();
}

int main() {
int n;
int a[110];
int v;
scanf("%d", &n);
Set st(n);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
}
for (int i = 1; i <= n; i++) {
scanf("%d", &v);
if (i + v <= n) st.Union(a[i], a[i + v]);
if (i - v >= 1) st.Union(a[i], a[i - v]);
}
for (int i = 1; i <= n; i++) {
if (!st.Same(i, a[i])) {
puts("NO");
return 0;
}
}
puts("YES");
return 0;
}