Skip to content

Commit 4e0bc2c

Browse files
authored
[20260310] BOJ / D5 / ACM Tax / 권혁준
1 parent 04160b1 commit 4e0bc2c

1 file changed

Lines changed: 238 additions & 0 deletions

File tree

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
```java
2+
import java.io.*;
3+
import java.util.*;
4+
5+
public class BOJ13892 {
6+
7+
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
8+
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
9+
static StringTokenizer st;
10+
11+
static int N, Q;
12+
static List<int[]>[] graph;
13+
static int[][] queries;
14+
15+
static List<Integer>[] chains, mergeSortTree;
16+
static int[] chainNum, chainIdx, depth, size, parent, order, reverseOrder, arr;
17+
static int orderCnt = 0;
18+
19+
public static void main(String[] args) throws Exception {
20+
int T = Integer.parseInt(br.readLine());
21+
while(T-- > 0) {
22+
N = Integer.parseInt(br.readLine());
23+
graph = new List[N+1];
24+
for(int i=1;i<=N;i++) {
25+
graph[i] = new ArrayList<>();
26+
}
27+
28+
for(int i=1;i<N;i++) {
29+
st = new StringTokenizer(br.readLine());
30+
int a = Integer.parseInt(st.nextToken());
31+
int b = Integer.parseInt(st.nextToken());
32+
int c = Integer.parseInt(st.nextToken());
33+
graph[a].add(new int[]{b,c});
34+
graph[b].add(new int[]{a,c});
35+
}
36+
37+
Q = Integer.parseInt(br.readLine());
38+
queries = new int[Q][];
39+
for(int i=0;i<Q;i++) {
40+
st = new StringTokenizer(br.readLine());
41+
int a = Integer.parseInt(st.nextToken());
42+
int b = Integer.parseInt(st.nextToken());
43+
queries[i] = new int[]{a,b};
44+
}
45+
46+
solve();
47+
}
48+
bw.close();
49+
}
50+
51+
public static void solve() throws Exception {
52+
// 1. Initialize
53+
54+
chains = new List[N+1];
55+
for(int i=1;i<=N;i++) {
56+
chains[i] = new ArrayList<>();
57+
}
58+
chainNum = new int[N+1];
59+
chainIdx = new int[N+1];
60+
depth = new int[N+1];
61+
size = new int[N+1];
62+
parent = new int[N+1];
63+
order = new int[N+1];
64+
reverseOrder = new int[N+1];
65+
arr = new int[N+1];
66+
67+
// 1-1. Heavy-Light Decomposition
68+
69+
dfs(1, 0);
70+
orderCnt = 0;
71+
hld(1, 0, 1, 0);
72+
73+
// 1-2. Merge Sort Tree
74+
75+
mergeSortTree = new List[4*N];
76+
for(int i=1;i<4*N;i++) {
77+
mergeSortTree[i] = new ArrayList<>();
78+
}
79+
80+
init(1, N, 1);
81+
82+
// 2. Solve
83+
84+
for(int[] query : queries) {
85+
int a = query[0], b = query[1];
86+
87+
// 2-1. Find LCA & path distance
88+
int dist = pathDistance(a, b);
89+
90+
// 2-2. Find median of path
91+
int median = kthValueOnPath(a, b, (dist+1) / 2);
92+
if(dist % 2 == 0) {
93+
median += kthValueOnPath(a, b, dist/2 + 1);
94+
}
95+
96+
// 2-3. Print result
97+
if(dist % 2 == 0) {
98+
bw.write((median/2) + "." + ((median%2)*5) + "\n");
99+
}
100+
else {
101+
bw.write(median + ".0\n");
102+
}
103+
104+
}
105+
}
106+
107+
public static void dfs(int cur, int par) {
108+
parent[cur] = par;
109+
size[cur] = 1;
110+
for(int[] edge : graph[cur]) if(edge[0] != par) {
111+
dfs(edge[0], cur);
112+
arr[edge[0]] = edge[1];
113+
size[cur] += size[edge[0]];
114+
}
115+
}
116+
117+
public static void hld(int cur, int par, int chainRoot, int dep) {
118+
depth[cur] = dep;
119+
chainNum[cur] = chainRoot;
120+
chainIdx[cur] = chains[chainRoot].size();
121+
chains[chainRoot].add(cur);
122+
order[cur] = ++orderCnt;
123+
reverseOrder[orderCnt] = cur;
124+
int h = -1;
125+
for(int[] edge : graph[cur]) if(edge[0] != par && (h == -1 || size[edge[0]] > size[h])) {
126+
h = edge[0];
127+
}
128+
if(h != -1) {
129+
hld(h, cur, chainRoot, dep);
130+
}
131+
for(int[] edge : graph[cur]) if(edge[0] != par && edge[0] != h) {
132+
hld(edge[0], cur, edge[0], dep + 1);
133+
}
134+
}
135+
136+
public static int pathDistance(int a, int b) {
137+
int len = 0;
138+
while(chainNum[a] != chainNum[b]) {
139+
if(depth[a] > depth[b]) {
140+
len += chainIdx[a] + 1;
141+
a = parent[chainNum[a]];
142+
}
143+
else {
144+
len += chainIdx[b] + 1;
145+
b = parent[chainNum[b]];
146+
}
147+
}
148+
return len + Math.abs(chainIdx[a] - chainIdx[b]);
149+
}
150+
151+
public static void init(int s, int e, int n) {
152+
if(s == e) {
153+
mergeSortTree[n].add(arr[reverseOrder[s]]);
154+
return;
155+
}
156+
int m = (s+e) >> 1;
157+
init(s, m, n*2);
158+
init(m+1, e, n*2+1);
159+
160+
int p1 = 0, p2 = 0;
161+
while(p1 < mergeSortTree[n*2].size() && p2 < mergeSortTree[n*2+1].size()) {
162+
int v1 = mergeSortTree[n*2].get(p1);
163+
int v2 = mergeSortTree[n*2+1].get(p2);
164+
if(v1 < v2) {
165+
mergeSortTree[n].add(v1);
166+
p1++;
167+
}
168+
else {
169+
mergeSortTree[n].add(v2);
170+
p2++;
171+
}
172+
}
173+
174+
while(p1 < mergeSortTree[n*2].size()) {
175+
mergeSortTree[n].add(mergeSortTree[n*2].get(p1++));
176+
}
177+
while(p2 < mergeSortTree[n*2+1].size()) {
178+
mergeSortTree[n].add(mergeSortTree[n*2+1].get(p2++));
179+
}
180+
}
181+
182+
public static int countLeqThanK(int s, int e, int l, int r, int k, int n) {
183+
if(l > r || l > e || r < s) return 0;
184+
if(l <= s && e <= r) {
185+
int lo = 0, hi = mergeSortTree[n].size(), mid = (lo + hi) >> 1;
186+
while(lo < hi) {
187+
if(mergeSortTree[n].get(mid) <= k) {
188+
lo = mid + 1;
189+
}
190+
else {
191+
hi = mid;
192+
}
193+
mid = (lo + hi) >> 1;
194+
}
195+
return mid;
196+
}
197+
int m = (s+e) >> 1;
198+
return countLeqThanK(s, m, l, r, k, n*2) + countLeqThanK(m+1, e, l, r, k, n*2+1);
199+
}
200+
201+
public static int kthValueOnPath(int a, int b, int k) {
202+
int s = 1, e = 100_000, m = (s+e) >> 1;
203+
while(s < e) {
204+
if(countOnPathLeqThanK(a, b, m) < k) {
205+
s = m + 1;
206+
}
207+
else {
208+
e = m;
209+
}
210+
m = (s+e) >> 1;
211+
}
212+
return m;
213+
}
214+
215+
public static int countOnPathLeqThanK(int a, int b, int k) {
216+
int ret = 0;
217+
218+
while(chainNum[a] != chainNum[b]) {
219+
if(depth[a] > depth[b]) {
220+
ret += countLeqThanK(1, N, order[chainNum[a]], order[a], k, 1);
221+
a = parent[chainNum[a]];
222+
}
223+
else {
224+
ret += countLeqThanK(1, N, order[chainNum[b]], order[b], k, 1);
225+
b = parent[chainNum[b]];
226+
}
227+
}
228+
if(chainIdx[a] > chainIdx[b]) {
229+
ret += countLeqThanK(1, N, order[b]+1, order[a], k, 1);
230+
}
231+
else {
232+
ret += countLeqThanK(1, N, order[a]+1, order[b], k, 1);
233+
}
234+
235+
return ret;
236+
}
237+
}
238+
```

0 commit comments

Comments
 (0)