제출 #956394

#제출 시각아이디문제언어결과실행 시간메모리
956394NonozeTwo Currencies (JOI23_currencies)C++17
28 / 100
472 ms135112 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; template<class T> struct segtree { vector<T> st; int n; T idElement; segtree(int nn, T idEl, vector<T> creation={}) { n=nn, idElement=idEl; st.resize(n*2, idElement); if (!creation.empty()) { for (int i=0; i<n; i++) st[i+n]=creation[i]; build(); } } void clear() { st.clear(); st.resize(2*n, idElement); } void build() { for (int i=n-1; i>0; i--) st[i] = combine(st[i<<1], st[i<<1|1]); } void update(int p, int val) { p+=n; for (st[p].fi+=vaut[p-n]*val, st[p].se+=val ; p > 1; p >>= 1) st[p>>1] = combine(st[p], st[p^1]); } T query(int l, int r) { T res = idElement; r++; for (l += n, r += n; l < r; l >>= 1, r >>= 1) { if (l&1) res = combine(res, st[l++]); if (r&1) res = combine(res, st[--r]); } return res; } T query(int r) {return query(0, r);} T combine(T l, T r) { T ans={l.first+r.first, l.second+r.second}; return ans; } }; multiset<int> sett; int ask(segtree<pair<int, int>> st, int s, int t, int a, int b) { int tot=sz(sett); if (tot==0) return a; int l=0, r=st.n-1, ans=0; while (l<=r) { int mid=(l+r)/2; if (st.query(mid).fi<=b) { l=mid+1; ans=mid; } else r=mid-1; } auto ub=sett.upper_bound(vaut[ans]); if (ub==sett.end()) return a; auto queryy=st.query(ans); int comp=queryy.se; b-=queryy.fi; comp+=b/(*ub); comp=tot-comp; if (comp<=0) comp=0; if (comp>a) comp=a+1; return a-comp; } void subtask3() { map<int, int> mp; for (int i=0; i<n; i++) { for (auto u: adj[i]) { mp[u.se]=1; } } mp[0]=1; int compteur=0; for (auto &u: mp) { u.se=compteur++; } segtree<pair<int, int>> st(compteur, {0, 0}); vaut.resize(compteur, 0); for (int i=0; i<n; i++) { auto temp=adj[i]; for (auto &u: temp) { vaut[mp[u.se]]=u.se; adj[i].erase({u.fi, u.se}); adj[i].insert({u.fi, 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 ((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=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]; if (i && s/square!=queries[i-1].fi[0]/square) { st.clear(); left=s, right=s; } while (right<empl[t]) { int toadd=nxt[ordre[right]].se; if (toadd!=-1) { st.update(toadd, 1); sett.insert(vaut[toadd]); } right++; } while (left>empl[s]) { left--; int toadd=nxt[ordre[left]].se; if (toadd!=-1) { st.update(toadd, 1); sett.insert(vaut[toadd]); } } while (left<empl[s]) { int toerase=nxt[ordre[left]].se; if (toerase!=-1) { st.update(toerase, -1); sett.erase(sett.find(vaut[toerase])); } left++; } while (right>empl[t]) { right--; int toerase=nxt[ordre[right]].se; if (toerase!=-1) { st.update(toerase, -1); sett.erase(sett.find(vaut[toerase])); } } answers[queries[i].se]=ask(st, 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...