Submission #377066

#TimeUsernameProblemLanguageResultExecution timeMemory
377066timg8710Valley (BOI19_valley)Java
100 / 100
1396 ms66600 KiB
// package olypmiads; import java.io.*; import java.util.ArrayList; import java.util.Arrays; import java.util.StringTokenizer; @SuppressWarnings("unchecked") public class valley { //1. root tree at exit //2. Use pref sum idea: pref[i] is the sum from root to i //pref[u] + pref[shop] - 2*pref[lca(sum, u)] //like many formulations involving LCA, we don't have to worry about it if we use offline processing, reduce the problem to a linear array as the DFS //is in progress static int[][] edges; static long[] ret; static int[] map; static long[] dp; static ArrayList<int[]>[] upQ; static ArrayList<long[]>[] adj; static long NEG = Long.MAX_VALUE/3; public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); PrintWriter pw = new PrintWriter(System.out); StringTokenizer st = new StringTokenizer(br.readLine()); int N = Integer.parseInt(st.nextToken()); int S = Integer.parseInt(st.nextToken()); int Q = Integer.parseInt(st.nextToken()); int E = Integer.parseInt(st.nextToken())-1; ret = new long[Q]; edges = new int[N-1][2]; upQ = new ArrayList[N]; for(int i= 0; i<upQ.length; i++) upQ[i] = new ArrayList<>(); //for offline processing adj = new ArrayList[N]; for (int i = 0; i < adj.length; i++) { adj[i] = new ArrayList<>();} for(int i = 0; i<N-1; i++) { st = new StringTokenizer(br.readLine()); int u = Integer.parseInt(st.nextToken())-1; int v = Integer.parseInt(st.nextToken())-1; long w = Integer.parseInt(st.nextToken()); adj[u].add(new long[]{v, w}); adj[v].add(new long[]{u, w}); edges[i] = new int[]{u, v}; } dp = new long[N]; //this is the dp of the lcas Arrays.fill(dp, NEG); for(int i = 0; i<S; i++){ dp[Integer.parseInt(br.readLine())-1] = 0; } precomp(E, -1, 0); // System.out.println(Arrays.toString(dp)); for(int i =0; i<Q; i++){ st = new StringTokenizer(br.readLine()); int e = Integer.parseInt(st.nextToken())-1; int u = Integer.parseInt(st.nextToken())-1; upQ[u].add(new int[]{edges[e][0], edges[e][1], i}); } SegTree pref = new SegTree(N); map = new int[N]; //mapping to in the pref ar Arrays.fill(map, -1); dfs(E, -1, 0, pref, 0); for(long i : ret) pw.println(i == -1 ? "escaped" : (i >= NEG ? "oo" : ""+i)); pw.close(); br.close(); } static void dfs(int u, int par, int idx, SegTree pref, long sum){ map[u] = idx; pref.update(1, idx, dp[u], 0, adj.length-1); for(int[] e : upQ[u]){ int block = Math.min(map[e[0]], map[e[1]]); if(block == -1){ ret[e[2]] = -1; }else{ ret[e[2]] = sum + pref.get(1, block+1, idx, 0, adj.length-1); } } for(long[] n : adj[u]){ if(n[0] != par) dfs((int)n[0], u, idx+1, pref, sum + n[1]); } map[u] = -1; pref.update(1, idx, -dp[u], 0, adj.length-1); } static long precomp(int u, int par, long sum){ for(long[] n : adj[u]){ if(n[0] == par) continue; dp[u] = Math.min(dp[u], precomp((int)n[0], u, sum + n[1]) + n[1]); } dp[u] -= sum; return dp[u] + sum; } static class SegTree { public long[] nodes; public SegTree(int N) { nodes = new long[4 * N]; } public long get(int gI, int l, int r, int gL, int gR) { if (l > r) { return NEG; } if (gL == l && gR == r) { return nodes[gI]; } int mid = (gR + gL) / 2; return Math.min( get(2 * gI, l, Math.min(r, mid), gL, mid), get(2 * gI + 1, Math.max(mid + 1, l), r, mid + 1, gR) ); } public long update(int gI, int idx, long val, int gL, int gR) { if (idx < gL || idx > gR) { return nodes[gI]; } if (gL == gR) { nodes[gI] = val; } else { nodes[gI] = Math.min( update(2 * gI, idx, val, gL, (gL + gR) / 2), update(2 * gI + 1, idx, val, (gL + gR) / 2 + 1, gR) ); } return nodes[gI]; } } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...