제출 #761863

#제출 시각아이디문제언어결과실행 시간메모리
761863senthetaTwo Currencies (JOI23_currencies)C++17
100 / 100
2072 ms80732 KiB
// author : sentheta aka vanwij #ifdef VANWIJ #include"/home/user/code/bits/stdc++.h" #else #include"bits/stdc++.h" #endif using namespace std; #define Int long long #define V vector #define pii pair<int,int> #define ff first #define ss second static mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count()); #define pow2(x) (1LL<<(x)) #define msb(x) (63-__builtin_clzll(x)) #define bitcnt(x) (__builtin_popcountll(x)) #define nl '\n' #define _ << ' ' << #define all(x) (x).begin(), (x).end() #define rep(i,a,b) for(int i = (int)(a); i < (int)(b); i++) #define dbg(x) if(1) cout << "?" << #x << " : " << (x) << endl << flush; #define int long long // const Int MOD = 1e9+7; const Int MOD = 998244353; Int bpow(Int a,Int b){ Int ret = 1; for(;b; a=a*a%MOD,b/=2) if(b&1) ret = ret*a%MOD; return ret; } Int inv(Int a){return bpow(a,MOD-2);} void solve(); int TC, ALLTC; signed main(){ ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cout << fixed << setprecision(7); // cin >> ALLTC; for(TC=1; TC<=ALLTC; TC++) solve(); return 0; solve(); } const int N = 1e5+5; const int LN = 18; int n, m, q; pii edg[N]; V<int> adj[N]; int root; // regular euler tour int dep[N], in[N], out[N], tim=1; void dfs_init(int x=root,int par=0){ in[x] = tim++; for(int y : adj[x]) if(y!=par){ dep[y] = dep[x]+1; dfs_init(y, x); } out[x] = tim-1; } // lca sparse table // duplicated euler tour int getMinDepth(int x,int y){ return (dep[x]<dep[y]) ? x : y; } struct Stable{ int v[2*N][LN]; void build(){ rep(lg,1,LN) for(int i=0; i+(1<<lg)-1<2*N; i++){ v[i][lg] = getMinDepth(v[i][lg-1], v[i+(1<<(lg-1))][lg-1]); } } int qry(int l,int r){ int lg = __lg(r-l+1); return getMinDepth(v[l][lg], v[r-(1<<lg)+1][lg]); } } stable; int st[N], stim=1; int getLca(int x,int y){ if(!(st[x]<st[y])) swap(x,y); return stable.qry(st[x], st[y]); } void dfs_stable(int x=root,int par=0){ st[x] = stim; stable.v[stim++][0] = x; for(int y : adj[x]) if(y!=par){ dfs_stable(y, x); stable.v[stim++][0] = x; } } // fenwick tree, range update, point query struct Fenw{ // int v[N]; // void reset(){ // rep(i,0,N) v[i] = 0; // } // void upd(int l,int r,int val){ // for(l++; l<N; l+=l&-l) v[l]+=val; // r++; // for(r++; r<N; r+=r&-r) v[r]-=val; // } // int qry(int i){ // int ret = 0; // for(i++; i; i-=i&-i) ret+=v[i]; // return ret; // } #define lc (v+1) #define rc (v+2*(mid-tl+1)) #define mid (tl+tr)/2 int lz[2*N]; void reset(){ rep(v,0,2*N) lz[v] = 0; } void upd(int l,int r,int val,int v=0,int tl=1,int tr=n){ if(r<tl || tr<l) return; if(l<=tl && tr<=r){ lz[v] += val; return; } upd(l,r,val, lc,tl,mid); upd(l,r,val, rc,mid+1,tr); } int qry(int i,int v=0,int tl=1,int tr=n){ if(tl==tr) return lz[v]; if(i<=mid) return lz[v] + qry(i, lc,tl,mid); else return lz[v] + qry(i, rc,mid+1,tr); } int getInPath(int x,int y){ return qry(in[x]) + qry(in[y]) - 2*qry(in[getLca(x,y)]); } #undef lc #undef rc #undef mid } counter, silver; // tax position and cost int pos[N], c[N]; // queries int qs[N], qt[N], qx[N], qy[N]; // max #taxes paid by silver int qans[N]; // range to check int ql[N], qr[N]; // queries to check V<int> tochk[N]; void solve(){ cin >> n >> m >> q; // input edges rep(e,1,n){ int u, v; cin >> u >> v; adj[u].push_back(v); adj[v].push_back(u); edg[e] = {u,v}; } root = rng()%n+1; dfs_init(); assert(tim-1==n); dfs_stable(); assert(stim-1==2*n-1); stable.build(); // rep(i,1,n+1) assert(getLca(i,i)==i); // input taxes V<int> txord; rep(i,0,m){ cin >> pos[i] >> c[i]; txord.push_back(i); // put this tax at child auto[u,v] = edg[pos[i]]; pos[i] = u ^ v ^ getMinDepth(u,v); } sort(all(txord),[&](int i,int j){ return c[i] < c[j]; }); // input queries rep(i,1,q+1){ cin >> qs[i] >> qt[i] >> qx[i] >> qy[i]; qans[i] = 0; ql[i] = 0; qr[i] = m-1; } // silver.getInPath(1,2); // return; // parallel binsearch while(1){ // rep(loop,0,LN){ // dbg(loop); bool unsolved = 0; rep(i,0,m) tochk[i].clear(); rep(i,1,q+1) if(ql[i]<=qr[i]){ tochk[(ql[i]+qr[i])/2].push_back(i); unsolved = 1; } if(!unsolved) break; counter.reset(); silver.reset(); // insert taxes rep(i,0,m){ // dbg(i); // insert tax into euler tour int idx = txord[i]; // tax ID int x = pos[idx]; counter.upd(in[x], out[x], 1); silver.upd(in[x], out[x], c[idx]); // check queries for(int j : tochk[i]){ // check whether have enough silver if(silver.getInPath(qs[j],qt[j]) <= qy[j]){ qans[j] = counter.getInPath(qs[j],qt[j]); ql[j] = i+1; } else{ qr[j] = i-1; } } } } counter.reset(); rep(idx,0,m){ int x = pos[idx]; counter.upd(in[x], out[x], 1); } // output answer rep(i,1,q+1){ int ans = qx[i]+qans[i] - counter.getInPath(qs[i],qt[i]); ans = max(ans, -1LL); cout << ans << nl; } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...