55import  java .util .*;
66import  java .io .*;
77
8+ /** 
9+  * Reference: https://www.codechef.com/viewsolution/12879967 
10+  */ 
811public  class  DISTNUM3  {
9-  private  static  final  int  MAX  = 100000 ;
10-  static  ArrayList <Integer >[] adj ;
11-  static  int  clock  = 0 , eulerTour [], start [], end [], V ;
12-  static  int  BLOCK_SIZE ;
13- 
14-  /* LCA <NlogN , logN> dependency : level , log , V , DP = new int[log(V) + 1][V + 1];, parent (for the first level of DP) */ 
12+  static  List <Integer >[] adj ;
13+  static  int  clock  = 0 , start [], end [], V ;
1514 static  int  DP [][];
1615 static  int  level [];
1716 static  int  parent [];
17+  static  int  distinctCount ;
18+  static  boolean  marked [];
19+  static  int  vertices [];
1820
1921 static  int  log (int  N ) {
2022 return  31  - Integer .numberOfLeadingZeros (N );
2123 }
2224
23-  static  void  binaryLift () {
25+  static  void  findAncestorsAtEachLevel () {
2426 System .arraycopy (parent , 1 , DP [0 ], 1 , V );
2527 for  (int  i  = 1 ; i  < DP .length ; i ++) {
2628 for  (int  j  = 1 ; j  <= V ; j ++) {
@@ -31,247 +33,204 @@ static void binaryLift() {
3133
3234 static  int  LCA (int  u , int  v ) {
3335 if  (level [v ] < level [u ]) {
34-  int  temp  = u ;
36+  final   int  temp  = u ;
3537 u  = v ;
3638 v  = temp ;
3739 }
3840 int  diff  = level [v ] - level [u ];
39-  while  (diff  > 0 ) {  // Bring v to the same level as u 
40-  int  log  = log (diff );
41+  while  (diff  > 0 ) {
42+  final   int  log  = log (diff );
4143 v  = DP [log ][v ];
4244 diff  -= (1  << log );
4345 }
4446 while  (u  != v ) {
4547 int  i  = log (level [u ]);
46-  for  (;  i  > 0  && DP [i ][u ] == DP [i ][v ]; ) 
48+  while  ( i  > 0  && DP [i ][u ] == DP [i ][v ]) { 
4749 i --;
48- 
50+  } 
4951 u  = DP [i ][u ];
5052 v  = DP [i ][v ];
5153 }
52- 
5354 return  u ;
5455 }
5556
56-  static  void  dfs (int  u , int  par , int  lev ) {
57+  static  void  dfs (final   int  u , final   int  par , final   int  lev ,  final   int []  eulerTour ) {
5758 eulerTour [clock ] = u ;
5859 start [u ] = clock ++;
5960 parent [u ] = par ;
6061 level [u ] = lev ;
61-  for  (int  v  : adj [u ])
62-  if  (v  != par )
63-  dfs (v , u , lev  + 1 );
64- 
62+  for  (final  int  v  : adj [u ]) {
63+  if  (v  != par ) {
64+  dfs (v , u , lev  + 1 , eulerTour );
65+  }
66+  }
6567 eulerTour [clock ] = u ;
6668 end [u ] = clock ++;
6769 }
6870
69- 
70-  static  class  Query  {
71-  int  L , R , numUpdatesLess , LCA , id ;
72- 
73-  public  Query (int  l , int  r , int  numUpdatesLess , int  lCA , int  id ) {
74-  L  = l ;
75-  R  = r ;
76-  this .numUpdatesLess  = numUpdatesLess ;
77-  LCA  = lCA ;
78-  this .id  = id ;
79-  }
80- 
81-  @ Override 
82-  public  String  toString () {
83-  return  String .format ("[L = %d R = %d updatesLess = %d LCA = %d id = %d]" , L , R , numUpdatesLess , LCA , id );
84-  }
85-  }
86- 
87-  static  class  Update  {
88-  int  idx , prevVal , newVal ;
89- 
90-  public  Update (int  idx , int  newVal , int  prevVal ) {
91-  this .idx  = idx ;
92-  this .newVal  = newVal ;
93-  this .prevVal  = prevVal ;
94-  }
95- 
96-  @ Override 
97-  public  String  toString () {
98-  return  String .format ("[idx = %d prevVal = %d newVal = %d" , idx , prevVal , newVal );
99-  }
100-  }
101- 
102-  static  class  MoComparator  implements  Comparator <Query > {
103-  @ Override 
104-  public  int  compare (Query  o1 , Query  o2 ) {
105-  if  (blockCache [o1 .L ] != blockCache [o2 .L ])
106-  return  blockCache [o1 .L ] - blockCache [o2 .L ];
107-  else  if  (blockCache [o1 .R ] != blockCache [o2 .R ])
108-  return  blockCache [o1 .R ] - blockCache [o2 .R ];
109-  else 
110-  return  o1 .numUpdatesLess  - o2 .numUpdatesLess ;
111-  }
112-  }
113- 
114-  static  int  freq [];
115-  static  int  distinctCount ;
116-  static  boolean  marked [];
117-  static  int  blockCache [];
118-  static  int  val [];
119-  static  HashMap <Integer , Integer > map ;
120- 
121-  static  void  visit (int  idx ) {
71+  static  void  visit (final  int  idx , final  int [] frequency ) {
12272 if  (marked [idx ]) {
123-  freq [ val [idx ]]--;
124-  if  (freq [ val [idx ]] == 0 )
73+  frequency [ vertices [idx ]]--;
74+  if  (frequency [ vertices [idx ]] == 0 ) { 
12575 distinctCount --;
76+  }
12677 } else  {
127-  freq [ val [idx ]]++;
128-  if  (freq [ val [idx ]] == 1 )
78+  frequency [ vertices [idx ]]++;
79+  if  (frequency [ vertices [idx ]] == 1 ) { 
12980 distinctCount ++;
81+  }
13082 }
131- 
13283 marked [idx ] = !marked [idx ];
13384 }
13485
135-  static  void  update (int  idx , int  newVal ) {
86+  static  void  update (final   int  idx , final   int  newVal ,  final   int []  frequency ) {
13687 if  (marked [idx ]) {
137-  visit (idx );
138-  val [idx ] = newVal ;
139-  visit (idx );
140-  } else 
141-  val [idx ] = newVal ;
142-  }
143- 
144-  static  int  countDistinct (int  u , int  v ) {
145-  int  lca  = LCA (u , v );
146-  BitSet  bitSet  = new  BitSet (map .size ());
147-  bitSet .set (val [lca ]);
148-  while  (u  != lca ) {
149-  bitSet .set (val [u ]);
150-  u  = parent [u ];
151-  }
152-  while  (v  != lca ) {
153-  bitSet .set (val [v ]);
154-  v  = parent [v ];
88+  visit (idx , frequency );
89+  vertices [idx ] = newVal ;
90+  visit (idx , frequency );
91+  } else  {
92+  vertices [idx ] = newVal ;
15593 }
156- 
157-  return  bitSet .cardinality ();
15894 }
15995
16096 public  static  void  main (String [] args ) throws  IOException  {
16197 final  InputReader  in  = new  InputReader (System .in );
162-  int  qSZ  = 0 , uSZ  = 0 ;
16398 V  = in .readInt ();
164-  int  Q  = in .readInt ();
165-  int  E  = V  - 1 ;
166-  Query  queries [] = new  Query [MAX ];
167-  Update  updates [] = new  Update [MAX ];
168-  map  = new  HashMap <>(); // Used to compress the keys 
169- 
99+  final  int  Q  = in .readInt ();
170100 adj  = new  ArrayList [V  + 1 ];
171101 for  (int  i  = 1 ; i  <= V ; i ++) {
172102 adj [i ] = new  ArrayList <>();
173103 }
174-  val  = new  int [V  + 1 ];
104+  vertices  = new  int [V  + 1 ];
175105 for  (int  i  = 1 ; i  <= V ; i ++) {
176-  val [i ] = in .readInt ();
106+  vertices [i ] = in .readInt ();
177107 }
108+  final  Map <Integer , Integer > map  = new  HashMap <>();
178109 for  (int  i  = 1 ; i  <= V ; i ++) {
179-  if  (!map .containsKey (val [i ])) {
180-  map .put (val [i ], map .size ());
181-  }
182-  val [i ] = map .get (val [i ]);
110+  map .putIfAbsent (vertices [i ], map .size ());
111+  vertices [i ] = map .get (vertices [i ]);
183112 }
184-  int  currVal [] = new  int [V  + 1 ];
185-  System .arraycopy (val , 0 , currVal , 0 , V  + 1 );
186-  while  (E -- > 0 ) {
113+  final  int  verticesCopy [] = new  int [V  + 1 ];
114+  System .arraycopy (vertices , 0 , verticesCopy , 0 , V  + 1 );
115+  final  int  edges  = V  - 1 ;
116+  for  (int  i  = 0 ; i  < edges ; i ++) {
187117 final  int  u  = in .readInt ();
188118 final  int  v  = in .readInt ();
189119 adj [u ].add (v );
190120 adj [v ].add (u );
191121 }
192122 start  = new  int [V  + 1 ];
193123 end  = new  int [V  + 1 ];
194-  eulerTour  = new  int [2  * (V  + 1 )];
124+  final   int []  eulerTour  = new  int [2  * (V  + 1 )];
195125 level  = new  int [V  + 1 ];
196126 marked  = new  boolean [V  + 1 ];
197127 DP  = new  int [log (V ) + 1 ][V  + 1 ];
198128 parent  = new  int [V  + 1 ];
199-  blockCache  = new  int [2  * (V  + 1 )];
200-  dfs (1 , 0 , 0 );
201-  binaryLift ();
202-  while  (Q -- > 0 ) {
203-  if  (in .readInt () == 1 ) { // Query 
129+  dfs (1 , 0 , 0 , eulerTour );
130+  findAncestorsAtEachLevel ();
131+  int  numberOfQueries  = 0 , numberOfUpdates  = 0 ;
132+  final  Query  queries [] = new  Query [Q ];
133+  final  Update  updates [] = new  Update [Q ];
134+  for  (int  i  = 0 ; i  < Q ; i ++) {
135+  if  (in .readInt () == 1 ) {
204136 final  int  u  = in .readInt ();
205137 final  int  v  = in .readInt ();
206138 final  Query  q ;
207-  if  (end [u ] < start [v ]) // Cousin Nodes 
208-  {
209-  q  = new  Query (end [u ], start [v ], uSZ , LCA (u , v ), qSZ );
139+  if  (start [v ] > end [u ]) {
140+  q  = new  Query (end [u ], start [v ], numberOfUpdates , LCA (u , v ), numberOfQueries );
210141 } else  if  (start [u ] > end [v ]) {
211-  q  = new  Query (end [v ], start [u ], uSZ , LCA (u , v ), qSZ );
212-  } else  // Ancestors 
213-  {
214-  q  = new  Query (Math .min (start [u ], start [v ]), Math .max (start [u ], start [v ]), uSZ , -1 , qSZ );
142+  q  = new  Query (end [v ], start [u ], numberOfUpdates , LCA (u , v ), numberOfQueries );
143+  } else  {
144+  q  = new  Query (Math .min (start [u ], start [v ]),
145+  Math .max (start [u ], start [v ]),
146+  numberOfUpdates ,
147+  -1 ,
148+  numberOfQueries );
215149 }
216-  queries [qSZ ++] = q ;
150+  queries [numberOfQueries ++] = q ;
217151 } else  {
218152 final  int  idx  = in .readInt ();
219153 int  newVal  = in .readInt ();
220-  if  (!map .containsKey (newVal )) {
221-  map .put (newVal , map .size ());
222-  }
154+  map .putIfAbsent (newVal , map .size ());
223155 newVal  = map .get (newVal );
224-  updates [uSZ ++] = new  Update (idx , newVal , currVal [idx ]);
225-  currVal [idx ] = newVal ;
156+  updates [numberOfUpdates ++] = new  Update (idx , newVal , verticesCopy [idx ]);
157+  verticesCopy [idx ] = newVal ;
226158 }
227159 }
228-  freq  = new  int [map .size ()];
229-  BLOCK_SIZE  = (int ) (Math .pow (2  * V , 2.0  / 3.0 ) + 1 );
230-  for  (int  i  = 0 ; i  < blockCache .length ; i ++) {
231-  blockCache [i ] = i  / BLOCK_SIZE ;
232-  }
233-  Arrays .sort (queries , 0 , qSZ , new  MoComparator ());
234-  final  int  ans [] = new  int [qSZ ];
160+  final  int  BLOCK_SIZE  = (int ) (Math .pow (2  * V , 2.0  / 3.0 ) + 1 );
161+  Arrays .sort (queries , 0 , numberOfQueries , (first , second ) -> {
162+  if  (first .L  / BLOCK_SIZE  != second .L  / BLOCK_SIZE ) {
163+  return  first .L  / BLOCK_SIZE  - second .L  / BLOCK_SIZE ;
164+  } else  if  (first .R  / BLOCK_SIZE  != second .R  / BLOCK_SIZE ) {
165+  return  first .R  / BLOCK_SIZE  - second .R  / BLOCK_SIZE ;
166+  } else  {
167+  return  first .updatesTillNow  - second .updatesTillNow ;
168+  }
169+  });
170+  final  int  ans [] = new  int [numberOfQueries ];
235171 int  moLeft  = -1 , moRight  = -1 ;
236-  int  currUpd  = 0 ;
237-  for  ( int   i  = 0 ;  i  <  qSZ ;  i ++) { 
238-    final   Query   q  =  queries [ i ]; 
239-  while  ( currUpd  <  q . numUpdatesLess ) { 
240-    final   Update   u  =  updates [ currUpd ]; 
241-  update ( u . idx ,  u . newVal ) ;
242-  currUpd ++ ;
172+  int  currentUpdateCount  = 0 ;
173+  final   int []  frequency  = new   int [ map . size ()]; 
174+  for  ( int   i  =  0 ;  i  <  numberOfQueries ;  i ++) { 
175+  final   Query   query  =  queries [ i ]; 
176+  while  ( currentUpdateCount  <  query . updatesTillNow ) { 
177+  final   Update   update  =  updates [ currentUpdateCount ++] ;
178+  update ( update . idx ,  update . newValue ,  frequency ) ;
243179 }
244-  while  (currUpd  > q .numUpdatesLess ) {
245-  final  Update  u  = updates [currUpd  - 1 ];
246-  update (u .idx , u .prevVal );
247-  currUpd --;
180+  while  (currentUpdateCount  > query .updatesTillNow ) {
181+  final  Update  update  = updates [--currentUpdateCount ];
182+  update (update .idx , update .previousValue , frequency );
248183 }
249-  while  (moLeft  < q .L  - 1 ) {
184+  while  (moLeft  < query .L  - 1 ) {
250185 moLeft ++;
251-  visit (eulerTour [moLeft ]);
186+  visit (eulerTour [moLeft ],  frequency );
252187 }
253-  while  (moLeft  >= q .L ) {
254-  visit (eulerTour [moLeft ]);
188+  while  (moLeft  >= query .L ) {
189+  visit (eulerTour [moLeft ],  frequency );
255190 moLeft --;
256191 }
257-  while  (moRight  < q .R ) {
192+  while  (moRight  < query .R ) {
258193 moRight ++;
259-  visit (eulerTour [moRight ]);
194+  visit (eulerTour [moRight ],  frequency );
260195 }
261-  while  (moRight  > q .R ) {
262-  visit (eulerTour [moRight ]);
196+  while  (moRight  > query .R ) {
197+  visit (eulerTour [moRight ],  frequency );
263198 moRight --;
264199 }
265-  if  (q .LCA  != -1 ) {
266-  visit (q .LCA );
200+  if  (query .LCA  != -1 ) {
201+  visit (query .LCA ,  frequency );
267202 }
268-  ans [q .id ] = distinctCount ;
269-  if  (q .LCA  != -1 ) {
270-  visit (q .LCA );
203+  ans [query .id ] = distinctCount ;
204+  if  (query .LCA  != -1 ) {
205+  visit (query .LCA ,  frequency );
271206 }
272207 }
208+  final  StringBuilder  stringBuilder  = new  StringBuilder ();
273209 for  (final  int  a  : ans ) {
274-  System . out . println ( a );
210+  stringBuilder . append ( a ). append ( '\n' );
275211 }
212+  System .out .println (stringBuilder );
213+  }
214+ }
215+ 
216+ class  Query  {
217+  final  int  L , R , updatesTillNow , LCA , id ;
218+ 
219+  public  Query (final  int  l , final  int  r , final  int  updatesTillNow , final  int  lCA , final  int  id ) {
220+  L  = l ;
221+  R  = r ;
222+  this .updatesTillNow  = updatesTillNow ;
223+  LCA  = lCA ;
224+  this .id  = id ;
225+  }
226+ }
227+ 
228+ class  Update  {
229+  final  int  idx , previousValue , newValue ;
230+ 
231+  public  Update (final  int  idx , final  int  newValue , final  int  previousValue ) {
232+  this .idx  = idx ;
233+  this .newValue  = newValue ;
234+  this .previousValue  = previousValue ;
276235 }
277- }  
236+ }
0 commit comments