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