Skip to content

Commit 26e69e9

Browse files
authored
[20260311] BOJ / D3 / LIS on Tree / 권혁준
1 parent 4e0bc2c commit 26e69e9

1 file changed

Lines changed: 271 additions & 0 deletions

File tree

Lines changed: 271 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,271 @@
1+
```java
2+
import java.io.*;
3+
import java.util.*;
4+
5+
public class BOJ33752 {
6+
7+
static class SegmentTree {
8+
int[] tree;
9+
SegmentTree(int size) {
10+
tree = new int[size*4];
11+
}
12+
13+
void update(int s, int e, int i, int v, int n) {
14+
if(s == e) {
15+
tree[n] = v;
16+
return;
17+
}
18+
int m = (s+e) >> 1;
19+
if(i <= m) {
20+
update(s, m, i, v, n*2);
21+
}
22+
else {
23+
update(m+1, e, i, v, n*2+1);
24+
}
25+
tree[n] = Math.max(tree[n*2], tree[n*2+1]);
26+
}
27+
28+
int find(int s, int e, int l, int r, int n) {
29+
if(l > r || l > e || r < s) return 0;
30+
if(l <= s && e <= r) return tree[n];
31+
int m = (s+e) >> 1;
32+
return Math.max(find(s, m, l, r, n*2), find(m+1, e, l, r, n*2+1));
33+
}
34+
}
35+
36+
static class Choice {
37+
int value, index;
38+
Choice(int value, int index) {
39+
this.value = value;
40+
this.index = index;
41+
}
42+
}
43+
44+
static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
45+
static BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
46+
static StringTokenizer st;
47+
48+
static int N;
49+
static List<Integer>[] graph;
50+
static int[][] infos;
51+
static int[] arr, in, out, parent;
52+
static Choice[] dec, asc, dec2, asc2;
53+
static int order = 0;
54+
static SegmentTree seg;
55+
56+
static List<Integer>[] ascLists, decLists;
57+
58+
public static void main(String[] args) throws Exception {
59+
// 0. Input
60+
61+
N = Integer.parseInt(br.readLine());
62+
arr = new int[N+1];
63+
infos = new int[N][2];
64+
graph = new List[N+1];
65+
66+
st = new StringTokenizer(br.readLine());
67+
for(int i=1;i<=N;i++) {
68+
graph[i] = new ArrayList<>();
69+
arr[i] = Integer.parseInt(st.nextToken());
70+
infos[i-1][0] = arr[i];
71+
infos[i-1][1] = i;
72+
}
73+
74+
for(int i=1;i<N;i++) {
75+
st = new StringTokenizer(br.readLine());
76+
int a = Integer.parseInt(st.nextToken());
77+
int b = Integer.parseInt(st.nextToken());
78+
graph[a].add(b);
79+
graph[b].add(a);
80+
}
81+
82+
int answer = solve(1);
83+
84+
bw.write(answer + "\n");
85+
bw.close();
86+
}
87+
88+
public static int solve(int root) throws Exception {
89+
// 1. Euler-Tour Technique
90+
91+
in = new int[N+1];
92+
out = new int[N+1];
93+
parent = new int[N+1];
94+
order = 0;
95+
dfs(root, 0);
96+
97+
// 2. Segment Tree
98+
99+
/// 2-1. LIS : leaf -> root
100+
101+
asc = new Choice[N+1];
102+
asc2 = new Choice[N+1];
103+
Arrays.sort(infos, (a, b) -> Integer.compare(a[0], b[0]));
104+
longestSubsequenceDP(infos, asc, asc2);
105+
106+
/// 2-2. LDS : leaf -> root
107+
108+
dec = new Choice[N+1];
109+
dec2 = new Choice[N+1];
110+
Arrays.sort(infos, (a, b) -> Integer.compare(b[0], a[0]));
111+
longestSubsequenceDP(infos, dec, dec2);
112+
113+
// 3. Find Answer
114+
115+
/// Case 1) LIS contains LCA, 2nd best dp
116+
117+
int answer = 1;
118+
for(int i=1;i<=N;i++) {
119+
if(dec[i].index == asc[i].index) {
120+
answer = Math.max(answer, Math.max(dec[i].value + asc2[i].value - 1, dec2[i].value + asc[i].value - 1));
121+
answer = Math.max(answer, Math.max(dec[i].value, asc[i].value));
122+
}
123+
else {
124+
answer = Math.max(answer, dec[i].value + asc[i].value - 1);
125+
}
126+
}
127+
128+
/// Case 2) LIS doesn't contains LCA, Smaller To Larger
129+
130+
ascLists = new List[N+1];
131+
decLists = new List[N+1];
132+
for(int i=1;i<=N;i++) {
133+
ascLists[i] = new ArrayList<>();
134+
decLists[i] = new ArrayList<>();
135+
}
136+
137+
answer = Math.max(answer, dfs2(1, 0));
138+
139+
return answer;
140+
}
141+
142+
public static void dfs(int cur, int par) {
143+
in[cur] = ++order;
144+
parent[cur] = par;
145+
for(int nxt : graph[cur]) if(nxt != par) {
146+
dfs(nxt, cur);
147+
}
148+
out[cur] = order;
149+
}
150+
151+
public static void longestSubsequenceDP(int[][] arr, Choice[] ch1, Choice[] ch2) {
152+
seg = new SegmentTree(N);
153+
for(int i=1;i<=N;i++) {
154+
ch1[i] = new Choice(1, 0);
155+
ch2[i] = new Choice(1, -1);
156+
}
157+
for(int i=0;i<N;) {
158+
int curValue = arr[i][0];
159+
List<Integer> updates = new ArrayList<>();
160+
while(i<N && arr[i][0] == curValue) {
161+
int curIndex = arr[i][1];
162+
for(int child : graph[curIndex]) if(child != parent[curIndex]) {
163+
int result = seg.find(1, N, in[child], out[child], 1) + 1;
164+
if(result > ch1[curIndex].value) {
165+
ch2[curIndex] = ch1[curIndex];
166+
ch1[curIndex] = new Choice(result, child);
167+
}
168+
else if(result > ch2[curIndex].value) {
169+
ch2[curIndex] = new Choice(result, child);
170+
}
171+
}
172+
updates.add(curIndex);
173+
i++;
174+
}
175+
176+
for(int node : updates) {
177+
seg.update(1, N, in[node], ch1[node].value, 1);
178+
}
179+
}
180+
}
181+
182+
public static int dfs2(int cur, int par) {
183+
int ret = 0;
184+
for(int nxt : graph[cur]) if(nxt != par) {
185+
ret = Math.max(ret, dfs2(nxt, cur));
186+
187+
if (ascLists[nxt].size() + decLists[nxt].size() > ascLists[cur].size() + decLists[cur].size()) {
188+
List<Integer> temp1 = ascLists[nxt];
189+
ascLists[nxt] = ascLists[cur];
190+
ascLists[cur] = temp1;
191+
List<Integer> temp2 = decLists[nxt];
192+
decLists[nxt] = decLists[cur];
193+
decLists[cur] = temp2;
194+
}
195+
196+
for(int i=0;i<ascLists[nxt].size();i++) {
197+
int nxtVal = ascLists[nxt].get(i);
198+
199+
int s = -1, e = decLists[cur].size()-1, m = (s+e+1)>>1;
200+
while(s < e) {
201+
int curr = decLists[cur].get(m);
202+
if(curr > nxtVal) {
203+
s = m;
204+
}
205+
else {
206+
e = m-1;
207+
}
208+
m = (s+e+1)>>1;
209+
}
210+
ret = Math.max(ret, m+i+2);
211+
}
212+
213+
for(int i=0;i<decLists[nxt].size();i++) {
214+
int nxtVal = decLists[nxt].get(i);
215+
216+
int s = -1, e = ascLists[cur].size()-1, m = (s+e+1)>>1;
217+
while(s < e) {
218+
int curr = ascLists[cur].get(m);
219+
if(curr < nxtVal) {
220+
s = m;
221+
}
222+
else {
223+
e = m-1;
224+
}
225+
m = (s+e+1)>>1;
226+
}
227+
ret = Math.max(ret, i+m+2);
228+
}
229+
230+
for(int i=0;i<ascLists[nxt].size();i++) {
231+
if(i >= ascLists[cur].size()) {
232+
ascLists[cur].add((int)1e9 + 7);
233+
}
234+
int curVal = ascLists[cur].get(i);
235+
int nxtVal = ascLists[nxt].get(i);
236+
if(nxtVal < curVal) {
237+
ascLists[cur].set(i, nxtVal);
238+
}
239+
}
240+
241+
for(int i=0;i<decLists[nxt].size();i++) {
242+
if(i >= decLists[cur].size()) {
243+
decLists[cur].add(0);
244+
}
245+
int curVal = decLists[cur].get(i);
246+
int nxtVal = decLists[nxt].get(i);
247+
if(nxtVal > curVal) {
248+
decLists[cur].set(i, nxtVal);
249+
}
250+
}
251+
252+
}
253+
254+
if(ascLists[cur].size() + 1 == asc[cur].value) {
255+
ascLists[cur].add(arr[cur]);
256+
}
257+
else {
258+
ascLists[cur].set(asc[cur].value-1, arr[cur]);
259+
}
260+
261+
if(decLists[cur].size() + 1 == dec[cur].value) {
262+
decLists[cur].add(arr[cur]);
263+
}
264+
else {
265+
decLists[cur].set(dec[cur].value-1, arr[cur]);
266+
}
267+
268+
return ret;
269+
}
270+
}
271+
```

0 commit comments

Comments
 (0)