제출 #956496

#제출 시각아이디문제언어결과실행 시간메모리
956496NonozeTwo Currencies (JOI23_currencies)C++17
28 / 100
5040 ms141320 KiB
/* * Author: Nonoze * Created: Sunday 31/03/2024 */ #include <bits/stdc++.h> using namespace std; #include <ext/pb_ds/assoc_container.hpp> #include <ext/pb_ds/tree_policy.hpp> using namespace __gnu_pbds; template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>; template<class T> using ordered_multiset = tree<T, null_type, less_equal<T>, rb_tree_tag, tree_order_statistics_node_update>; typedef long long ll; #define int long long #ifdef _IN_LOCAL #include <bits/DebugTemplate.h> #else #define dbg(...) ; #endif #define sz(x) (int)(x.size()) #define all(x) (x).begin(), (x).end() #define rall(x) (x).rbegin(), (x).rend() #define pb push_back #define mp make_pair #define fi first #define se second #define endl '\n' #define endlfl '\n' << flush #define quit(x) cout << x << endl, return; const int MOD = 1e9+7; const ll inf = 1e18; template<typename T> constexpr bool cmax(T &a, const T &b) { return a < b ? a = b, 1 : 0; } template<typename T> constexpr bool cmin(T &a, const T &b) { return b < a ? a = b, 1 : 0; } void solve(); signed main() { ios::sync_with_stdio(0); cin.tie(0); int tt=1; // cin >> tt; while(tt--) solve(); return 0; } int n, m, q; vector<set<pair<int, int>>> adj; vector<int> depth, nb; vector<vector<int>> up; int base=0; void dfs(int s, int prec=-1) { for (auto u: adj[s]) { if (u.fi==prec) continue; nb[u.fi]=nb[s]+(u.se?1:0); if (u.se) base=u.se; depth[u.fi]=depth[s]+1; up[u.fi][0]=s; for (int i=1; i<20; i++) { up[u.fi][i]=up[ up[u.fi][i-1] ][i-1]; } dfs(u.fi, s); } } int get_lca(int a, int b) { if (depth[a]<depth[b]) swap(a, b); int k=depth[a]-depth[b]; for (int i=0; i<20; i++) { if (k&(1<<i)) { a=up[a][i]; } } if (a==b) return a; for (int i=19; i>=0; i--) { if (up[a][i]!=up[b][i]) { a=up[a][i]; b=up[b][i]; } } return up[a][0]; } void subtask2() { depth.resize(n), nb.resize(n), up.resize(n, vector<int>(20)); dfs(0); while (q--) { int s, t, a, b; cin >> s >> t >> a >> b; int lca=get_lca(--s, --t); int sumnb=nb[s]+nb[t]-2*nb[lca]; int take=b/base; int res=-1; take=sumnb-take; if (take<=0) { cout << a << endl; continue; } cmax(res, a-take); cout << res << endl; } } vector<int> vaut, contains, sqr, nbelements; int tot=0, squarevaut; int ask(int s, int t, int a, int b) { int comp=0, empl=0; for (; empl<sz(sqr) && sqr[empl]<=b; empl++) { b-=sqr[empl]; comp+=nbelements[empl]; } for (empl*=squarevaut; empl<sz(contains) && vaut[empl]*contains[empl]<=b; empl++) { b-=contains[empl]*vaut[empl]; comp+=contains[empl]; } return max(-1LL, a-tot+comp); } void subtask3() { map<int, int> mp; for (int i=0; i<n; i++) { for (auto u: adj[i]) { if (u.fi<i) continue; mp[u.se]++; } } mp[0]++; int compteur=0; for (auto &u: mp) { int sz=u.se; u.se=compteur; compteur+=sz; } squarevaut=sqrt(compteur); vaut.resize(compteur, 0), contains.resize(compteur, 0), sqr.resize(squarevaut+5, 0), nbelements.resize(squarevaut+5, 0); for (int i=0; i<n; i++) { auto temp=adj[i]; for (auto &u: temp) { if (u.fi<i) continue; vaut[mp[u.se]]=u.se; adj[i].erase({u.fi, u.se}); adj[i].insert({u.fi, mp[u.se]}); adj[u.fi].erase({i, u.se}); adj[u.fi].insert({i, mp[u.se]++}); } } vector<int> ordre(1, 0); vector<pair<int, int>> nxt(n, {-1, -1}); vector<int> empl(n, 0); int lst=-1; for (int i=0; i<n; i++) { for (auto u: adj[ordre.back()]) { if (u.fi!=lst) { nxt[ordre.back()]={u.fi, u.se}; lst=ordre.back(); ordre.push_back(u.fi); empl[ordre.back()]=sz(ordre)-1; break; } } } vector<int> answers(q); vector<pair<vector<int>, int>> queries; for (int i=0; i<q; i++) { int s, t, a, b; cin >> s >> t >> a >> b; if (--s>--t) swap(s, t); queries.push_back({{s, t, a, b}, i}); } int square=sqrt(n); sort(all(queries), [&](auto &a, auto &b){ if ((int)(a.fi[0]/square)!=(int)(b.fi[0]/square)) return (int)(a.fi[0]/square)<(int)(b.fi[0]/square); return a.fi[1]<b.fi[1]; }); int left=empl[queries[0].fi[0]], right=left; for (int i=0; i<q; i++) { int s=queries[i].fi[0], t=queries[i].fi[1]; while (right<empl[t]) { sqr[nxt[ordre[right]].se/squarevaut]+=vaut[nxt[ordre[right]].se]; contains[nxt[ordre[right]].se]++; nbelements[nxt[ordre[right]].se/squarevaut]++; tot++; right++; } while (left>empl[s]) { left--; sqr[nxt[ordre[left]].se/squarevaut]+=vaut[nxt[ordre[left]].se]; contains[nxt[ordre[left]].se]++; nbelements[nxt[ordre[left]].se/squarevaut]++; tot++; } while (left<empl[s]) { sqr[nxt[ordre[left]].se/squarevaut]-=vaut[nxt[ordre[left]].se]; contains[nxt[ordre[left]].se]--; nbelements[nxt[ordre[left]].se/squarevaut]--; tot--; left++; } while (right>empl[t]) { right--; sqr[nxt[ordre[right]].se/squarevaut]-=vaut[nxt[ordre[right]].se]; contains[nxt[ordre[right]].se]--; nbelements[nxt[ordre[right]].se/squarevaut]--; tot--; } answers[queries[i].se]=ask(s, t, queries[i].fi[2], queries[i].fi[3]); } for (auto u: answers) cout << u << endl; } void solve() { cin >> n >> m >> q; adj.resize(n); bool sub3=true; vector<pair<int, int>> edges; for (int i=1; i<n; i++) { int u, v; cin >> u >> v; edges.push_back({--u, --v}); if (v!=u+1) sub3=false; adj[u].insert({v, 0}); adj[v].insert({u, 0}); } vector<stack<int>> updates(n-1); for (int i=0; i<m; i++) { int p, c; cin >> p >> c; updates[--p].push(c); } for (int i=0; i<sz(updates); i++) { if (updates[i].empty()) continue; auto act=updates[i]; int u=edges[i].fi, v=edges[i].se; adj[u].erase({v, 0}); adj[v].erase({u, 0}); adj[u].insert({v, act.top()}); adj[v].insert({u, act.top()}); int weightbase=act.top(); act.pop(); while (!act.empty()) { int weight=act.top(); act.pop(); adj[u].erase({v, weightbase}); adj[v].erase({u, weightbase}); adj[u].insert({n, weight}); adj.push_back({}); adj[n].insert({u, weight}); adj[v].insert({n, weightbase}); adj[n].insert({v, weightbase}); u=n; n++; } } if (sub3) return subtask3(); return subtask2(); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...