// Karol Kosinski #include <cstdio> #include <algorithm> #include <vector> #define FOR(i,a,b) for(int i=(a);i<(b);++i) //#define DEBUG(args...) printf(args) #define DEBUG(args...) #define NX 200003 #define KX 500003 using namespace std; typedef long long LG; struct edge { int aim, no; }; struct reaction { int c, d, no, step; } R[KX]; bool operator < (const reaction &x, const reaction &y) { if(x.step - y.step != 0) return x.step - y.step < 0; return x.no - y.no < 0; } int n, m, k, counter; LG res; int A[21][2*NX]; int First[NX], G[NX]; bool Used[NX]; vector<edge> V[NX]; void read_tree() { FOR(i,0,m) { int a, b; scanf("%d%d", &a, &b); edge e = (edge){ a, i }; V[b].push_back(e); Used[a] = true; DEBUG("= (%2d) %d -> %d\n", i, b, a); } int tmp = m; FOR(i,1,n+1) { if(Used[i]) continue; edge e = (edge){ i, tmp++ }; V[0].push_back(e); DEBUG("+ (%2d) %d -> %d\n", tmp-1, 0, i); } } void visit_tree(int u, int num) { First[u] = counter; A[0][counter++] = num; DEBUG("%2d ", num); vector<edge>::iterator it = V[u].begin(); while(it != V[u].end()) { visit_tree(it->aim, it->no); A[0][counter++] = it->no; DEBUG("%2d ", it->no); ++it; } } void build_answers() { DEBUG("\n"); for(int j=1, d=1; d<counter; ++j, d*=2) { FOR(i,0,counter) { if( i + d >= counter ) A[j][i] = A[j-1][i]; else A[j][i] = max( A[j-1][i], A[j-1][i+d] ); DEBUG("%2d ", A[j][i]); } DEBUG("\n"); } } int query(int u, int v) { int j = 0, d = 1, a = min( First[u], First[v] ), b = max( First[u], First[v] ); while( d <= b - a ) ++j, d *= 2; return max( A[j-1][a+1], A[j-1][b-d/2+1] ); } void process_queries() { FOR(i,0,k) { int a, b; scanf("%d%d", &a, &b); R[i] = (reaction){ a, b, i, query(a, b) }; DEBUG("*** [%d]: ", i); DEBUG("( %d, %d ) -> %d\n", a, b, R[i].step); } sort(R, R + k); FOR(i,0,k) { reaction &r = R[i]; if(r.step >= m) break; DEBUG("===== [%d]: ", r.no); DEBUG("( %d, %d ) -> %d\n", r.c, r.d, r.step); int aux = min( G[r.c], G[r.d] ); G[r.c] -= aux, G[r.d] -= aux; res += 2 * aux; DEBUG(" res = %lld\n", res); DEBUG(" [%d]: ", r.no); DEBUG("( %d, %d ) -> %d\n", r.c, r.d, r.step); } } int main() { scanf("%d%d%d", &n, &m, &k); FOR(i,1,n+1) scanf("%d", G + i); read_tree(); visit_tree(0, -1); build_answers(); process_queries(); printf("%lld\n", res); return 0; }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | // Karol Kosinski #include <cstdio> #include <algorithm> #include <vector> #define FOR(i,a,b) for(int i=(a);i<(b);++i) //#define DEBUG(args...) printf(args) #define DEBUG(args...) #define NX 200003 #define KX 500003 using namespace std; typedef long long LG; struct edge { int aim, no; }; struct reaction { int c, d, no, step; } R[KX]; bool operator < (const reaction &x, const reaction &y) { if(x.step - y.step != 0) return x.step - y.step < 0; return x.no - y.no < 0; } int n, m, k, counter; LG res; int A[21][2*NX]; int First[NX], G[NX]; bool Used[NX]; vector<edge> V[NX]; void read_tree() { FOR(i,0,m) { int a, b; scanf("%d%d", &a, &b); edge e = (edge){ a, i }; V[b].push_back(e); Used[a] = true; DEBUG("= (%2d) %d -> %d\n", i, b, a); } int tmp = m; FOR(i,1,n+1) { if(Used[i]) continue; edge e = (edge){ i, tmp++ }; V[0].push_back(e); DEBUG("+ (%2d) %d -> %d\n", tmp-1, 0, i); } } void visit_tree(int u, int num) { First[u] = counter; A[0][counter++] = num; DEBUG("%2d ", num); vector<edge>::iterator it = V[u].begin(); while(it != V[u].end()) { visit_tree(it->aim, it->no); A[0][counter++] = it->no; DEBUG("%2d ", it->no); ++it; } } void build_answers() { DEBUG("\n"); for(int j=1, d=1; d<counter; ++j, d*=2) { FOR(i,0,counter) { if( i + d >= counter ) A[j][i] = A[j-1][i]; else A[j][i] = max( A[j-1][i], A[j-1][i+d] ); DEBUG("%2d ", A[j][i]); } DEBUG("\n"); } } int query(int u, int v) { int j = 0, d = 1, a = min( First[u], First[v] ), b = max( First[u], First[v] ); while( d <= b - a ) ++j, d *= 2; return max( A[j-1][a+1], A[j-1][b-d/2+1] ); } void process_queries() { FOR(i,0,k) { int a, b; scanf("%d%d", &a, &b); R[i] = (reaction){ a, b, i, query(a, b) }; DEBUG("*** [%d]: ", i); DEBUG("( %d, %d ) -> %d\n", a, b, R[i].step); } sort(R, R + k); FOR(i,0,k) { reaction &r = R[i]; if(r.step >= m) break; DEBUG("===== [%d]: ", r.no); DEBUG("( %d, %d ) -> %d\n", r.c, r.d, r.step); int aux = min( G[r.c], G[r.d] ); G[r.c] -= aux, G[r.d] -= aux; res += 2 * aux; DEBUG(" res = %lld\n", res); DEBUG(" [%d]: ", r.no); DEBUG("( %d, %d ) -> %d\n", r.c, r.d, r.step); } } int main() { scanf("%d%d%d", &n, &m, &k); FOR(i,1,n+1) scanf("%d", G + i); read_tree(); visit_tree(0, -1); build_answers(); process_queries(); printf("%lld\n", res); return 0; } |