제출 #768590

#제출 시각아이디문제언어결과실행 시간메모리
768590danikoynovTwo Currencies (JOI23_currencies)C++14
100 / 100
2037 ms84696 KiB
#include<bits/stdc++.h> #define endl '\n' using namespace std; typedef long long ll; void speed() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); } const ll maxn = 1e5 + 10; struct checkpoll { ll p, c; void read() { cin >> p >> c; } bool operator < (const checkpoll &t) const { return c < t.c; } } cp[maxn]; struct citizen { ll s, t, x, y; void read() { cin >> s >> t >> x >> y; } } ct[maxn]; ll n, m, q; vector < ll > adj[maxn]; pair < ll, ll > road[maxn]; void input() { cin >> n >> m >> q; for (ll i = 1; i < n; i ++) { ll a, b; cin >> a >> b; road[i] = {a, b}; adj[a].push_back(b); adj[b].push_back(a); } for (ll i = 1; i <= m; i ++) cp[i].read(); for (ll i = 1; i <= q; i ++) ct[i].read(); } ll tin[maxn], tout[maxn], timer, occ[2 * maxn]; ll par[maxn], depth[maxn]; void euler_tour(ll v = 1, ll p = 0) { occ[++ timer] = v; tin[v] = timer; for (ll u : adj[v]) { if (u == p) continue; depth[u] = depth[v] + 1; par[u] = v; euler_tour(u, v); occ[++ timer] = v; } tout[v] = timer; } const ll maxlog = 20; struct sparse_table { ll lg[2 * maxn], dp[maxlog][2 * maxn]; void build_sparse_table() { for (ll i = 1; i <= timer; i ++) { lg[i] = lg[i / 2] + 1; dp[0][i] = occ[i]; } for (ll j = 1; j < lg[timer]; j ++) { for (ll i = 1; i <= timer - (1 << j) + 1; i ++) { dp[j][i] = dp[j - 1][i + (1 << (j - 1))]; if (depth[dp[j - 1][i]] < depth[dp[j][i]]) dp[j][i] = dp[j - 1][i]; } } /**cout << "---------------" << endl; for (ll j = 0; j < lg[timer]; j ++, cout << endl) for (ll i = 1; i <= timer; i ++) cout << dp[j][i] << " ";*/ } ll lca_query(ll v, ll u) { ll l = tin[v], r = tin[u]; if (l > r) swap(l, r); ll len = lg[r - l + 1] - 1, lca = dp[len][r - (1 << len) + 1]; ///cout << "lca " << v << " " << u << " " << l << " " << r << endl; if (depth[dp[len][l]] < depth[lca]) lca = dp[len][l]; return lca; } }; sparse_table st; struct fenwick { ll fen[2 * maxn]; void add(ll pos, ll val) { for (ll i = pos; i <= timer; i += (i & -i)) fen[i] += val; } ll sum(ll pos) { ll s = 0; for (ll i = pos; i > 0; i -= (i & -i)) s += fen[i]; return s; } void range_update(ll left, ll right, ll val) { add(left, val); add(right + 1, - val); } ll query(ll pos) { return sum(pos); } }; fenwick gold, silver; pair < ll, ll > range[maxn]; vector < ll > upd[maxn]; ll binary_position(ll val) { ll left = 1, right = m; while(left <= right) { ll mid = left + (right - left) / 2; if (cp[mid].c <= val) left = mid + 1; else right = mid - 1; } return right; } ll ans[maxn]; pair < ll, ll > avab[maxn]; void parallel_binary_search() { for (ll i = 1; i <= q; i ++) { range[i] = {0, 1e9 + 10}; } for (ll i = 1; i < n; i ++) { if (depth[road[i].first] < depth[road[i].second]) swap(road[i].first, road[i].second); } /**for (ll i = 1; i <= m; i ++) { cout << road[cp[i].p].first << endl; }*/ sort(cp + 1, cp + m + 1); while(true) { bool done = true; for (ll i = 0; i <= m; i ++) upd[i].clear(); for (ll i = 1; i <= q; i ++) { if (range[i].first <= range[i].second) { done = false; ll mid = (range[i].first + (range[i].second - range[i].first) / 2); ll pos = binary_position(mid); upd[pos].push_back(i); } } if (done) break; //for (ll i = 1; i <= m; i ++) // gold.range_update(tin[cp[i].p], tout[cp[i].p], 1); /**cout << "-------------" << endl; for (ll i = 1; i <= m; i ++) cout << range[i].first << " " << range[i].second << endl;*/ for (ll i = 0; i <= m; i ++) { if (i != 0) { silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], cp[i].c); } for (ll idx : upd[i]) { ll lca = st.lca_query(ct[idx].s, ct[idx].t); ll val = silver.query(tin[ct[idx].s]) + silver.query(tin[ct[idx].t]); val = val - 2 * silver.query(tin[lca]); ///co ///cout << idx << " : " << val << " -- " << lca << endl; /**if (idx == 6) { cout << ct[idx].s << " " << ct[idx].t << " " << val << " " << lca << " " << i << endl; }*/ ll mid = (range[idx].first + (range[idx].second - range[idx].first) / 2); if (val > ct[idx].y) range[idx].second = mid - 1; else range[idx].first = mid + 1; } } for (ll i = 1; i <= m; i ++) silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -cp[i].c); } for (ll i = 0; i <= m; i ++) upd[i].clear(); for (ll i = 1; i <= q; i ++) { ll pos = binary_position(range[i].first); upd[pos].push_back(i); } for (ll i = 1; i <= m; i ++) { gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], 1); } for (ll i = 0; i <= m; i ++) { if (i != 0) { silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], cp[i].c); gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -1); } /**cout << "step" << endl; cout << i << endl; for (ll j = 1; j <= n; j ++) cout << gold.query(tin[j]) << " "; cout << endl; cout << "order" << endl; for (ll j = 1; j <= timer; j ++) cout << occ[j] << " "; cout << endl;*/ for (ll idx : upd[i]) { ll lca = st.lca_query(ct[idx].s, ct[idx].t); ll val = silver.query(tin[ct[idx].s]) + silver.query(tin[ct[idx].t]); val = val - 2 * silver.query(tin[lca]); ll min_gold = gold.query(tin[ct[idx].s]) + gold.query(tin[ct[idx].t]); ///cout << "gold " << min_gold << " " << gold.query(tinendl; min_gold = min_gold - 2 * gold.query(tin[lca]); //cout << idx << " : " << min_gold << " " << i << " lca " << lca << endl; avab[idx].second = min_gold; } } for (ll i = 1; i <= m; i ++) silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -cp[i].c); for (ll i = 0; i <= m; i ++) upd[i].clear(); for (ll i = 1; i <= q; i ++) { ll pos = binary_position(range[i].second); upd[pos].push_back(i); } for (ll i = 1; i <= m; i ++) { gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], 1); } for (ll i = 0; i <= m; i ++) { if (i != 0) { silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], cp[i].c); gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -1); } /**cout << "step" << endl; cout << i << endl; for (ll j = 1; j <= n; j ++) cout << gold.query(tin[j]) << " "; cout << endl; cout << "order" << endl; for (ll j = 1; j <= timer; j ++) cout << occ[j] << " "; cout << endl;*/ for (ll idx : upd[i]) { ll lca = st.lca_query(ct[idx].s, ct[idx].t); ll val = silver.query(tin[ct[idx].s]) + silver.query(tin[ct[idx].t]); val = val - 2 * silver.query(tin[lca]); ll min_gold = gold.query(tin[ct[idx].s]) + gold.query(tin[ct[idx].t]); ///cout << "gold " << min_gold << " " << gold.query(tinendl; min_gold = min_gold - 2 * gold.query(tin[lca]); //cout << idx << " : " << min_gold << " " << i << " lca " << lca << endl; ll to_fill = min_gold - avab[idx].second, cnt = range[idx].first; ll cn = min(to_fill, (ct[idx].y - val) / cnt); ll left_gold = ct[idx].x - min_gold + cn; if (left_gold < 0) left_gold = - 1; ans[idx] = left_gold; } } for (ll i = 1; i <= m; i ++) silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -cp[i].c); for (ll i = 1; i <= q; i ++) cout << ans[i] << endl; } void solve() { input(); euler_tour(1, 0); st.build_sparse_table(); parallel_binary_search(); } int main() { speed(); solve(); return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...