今天悲剧的第一题没看懂题,好吧,不会做,B 题最简单,放出来。
这题的思路实际上是并查集,先定义一个数组 s t st s t 表示现在的状态,目标状态是 1 , 2 , 3 , ⋯ , n 1,2,3,\cdots,n 1 , 2 , 3 , ⋯ , n ,那么,每次查找 i i i 和 i + v [ i ] i+v[i] i + v [ i ] 和 i − v [ i ] i-v[i] i − v [ i ] 三个数,把他们合并,表示他们可以互相转换,那么用 O ( n ) O(n) O ( n ) 的复杂度扫一遍,可以把全部的元素属于什么集合预处理出来,最后只要判断 s t [ i ] st[i] s t [ i ] 和 i i i 是不是一个集合里的就可以了。
今天无聊复习 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 ; }