|
| 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