今天悲剧的第一题没看懂题,好吧,不会做,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 ; }