제출 #957448

#제출 시각아이디문제언어결과실행 시간메모리
957448NonozeTwo Currencies (JOI23_currencies)C++17
100 / 100
2434 ms200540 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, in, out, id; vector<vector<int>> nxt; vector<vector<int>> up; int curr=0, toadd=-1; void dfs(int s, int prec=-1) { id.push_back(s), in[s]=curr++; nxt.push_back({}); for (auto u: adj[s]) { if (u.fi==prec) continue; if (id.back()==s) nxt[curr-1].push_back(u.se); if (toadd!=-1) nxt[toadd].push_back(u.se), toadd=-1; 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); nxt[curr-1].push_back(-u.se); toadd=curr-1; } if (sz(adj)<=2) toadd=-1; id.push_back(s), out[s]=curr++; nxt.push_back({}); } 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]; } vector<int> vaut, contains, sqr, nbelements; int tot=0, squarevaut; int ask(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 resolve() { 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]++}); } } depth.resize(n), in.resize(n), out.resize(n), up.resize(n, vector<int>(20)); dfs(0); 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; s--, t--; if (in[s]>in[t]) swap(s, t); int l, r, lca=get_lca(s, t); if (lca==s) l=in[s], r=in[t]; else l=out[s], r=in[t]; queries.push_back({{l, r, a, b}, i}); } int square=sqrt(2*n); sort(all(queries), [&](auto &a, auto &b){ if (a.fi[0]/square!=b.fi[0]/square) return a.fi[0]/square<b.fi[0]/square; return a.fi[1]<b.fi[1]; }); int left=0, right=0; for (int i=0; i<q; i++) { int l=queries[i].fi[0], r=queries[i].fi[1]; while (right<r) { for (auto u: nxt[right]) { if (!u) continue; int empl=abs(u), sign=(contains[empl]?-1:1); sqr[empl/squarevaut]+=vaut[empl]*sign; contains[empl]+=sign; nbelements[empl/squarevaut]+=sign; tot+=sign; } right++; } while (left>l) { left--; for (auto u: nxt[left]) { if (!u) continue; int empl=abs(u), sign=(contains[empl]?-1:1); sqr[empl/squarevaut]+=vaut[empl]*sign; contains[empl]+=sign; nbelements[empl/squarevaut]+=sign; tot+=sign; } } while (left<l) { for (auto u: nxt[left]) { if (!u) continue; int empl=abs(u), sign=(contains[empl]?-1:1); sqr[empl/squarevaut]+=vaut[empl]*sign; contains[empl]+=sign; nbelements[empl/squarevaut]+=sign; tot+=sign; } left++; } while (right>r) { right--; for (auto u: nxt[right]) { if (!u) continue; int empl=abs(u), sign=(contains[empl]?-1:1); sqr[empl/squarevaut]+=vaut[empl]*sign; contains[empl]+=sign; nbelements[empl/squarevaut]+=sign; tot+=sign; } } answers[queries[i].se]=ask(queries[i].fi[2], queries[i].fi[3]); } for (auto u: answers) cout << u << endl; } void solve() { cin >> n >> m >> q; adj.resize(n); vector<pair<int, int>> edges; for (int i=1; i<n; i++) { int u, v; cin >> u >> v; edges.push_back({--u, --v}); 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++; } } resolve(); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...