제출 #933490

#제출 시각아이디문제언어결과실행 시간메모리
933490velislavgarkovTwo Currencies (JOI23_currencies)C++14
30 / 100
1812 ms97656 KiB
#include <iostream> #include <algorithm> #include <vector> #include <cstring> using namespace std; #define endl '\n' const int MAXN=1e5+10; struct Edge { int a, b, to; }; struct Checkpoint { long long c; int subt; bool friend operator < (Checkpoint a, Checkpoint b) { return a.c<b.c; } }; struct Node { long long sum, active; int l, r; }; vector <pair <int,int> > v[MAXN]; Checkpoint p[MAXN]; Edge ed[MAXN]; Node tree[100*MAXN]; int root[MAXN], cnt; int in[MAXN], out[MAXN], dep[MAXN], sp[MAXN][20]; int n, m, q; int build_tree(int l, int r) { int cur=cnt; cnt++; tree[cur].sum=tree[cur].active=0; if (l==r) return cur; int mid=(l+r)/2; tree[cur].l=build_tree(l,mid); tree[cur].r=build_tree(mid+1,r); return cur; } int update(int node, int l, int r, int ql, int qr, long long ch) { int newc=cnt; cnt++; tree[newc]=tree[node]; if (l>=ql && r<=qr) { tree[newc].sum+=ch; tree[newc].active++; return newc; } int mid=(l+r)/2; if (!(ql>mid || qr<l)) tree[newc].l=update(tree[node].l,l,mid,ql,qr,ch); if (!(ql>r || qr<mid+1)) tree[newc].r=update(tree[node].r,mid+1,r,ql,qr,ch); return newc; } long long query(int node, int l, int r, int qind, int type) { if (l==r) { if (type==0) return tree[node].sum; return tree[node].active; } int mid=(l+r)/2; long long res; if (qind<=mid) res=query(tree[node].l,l,mid,qind,type); else res=query(tree[node].r,mid+1,r,qind,type); if (type==0) res+=tree[node].sum; else res+=tree[node].active; return res; } void dfs(int x, int p) { cnt++; in[x]=cnt; for (auto i:v[x]) { if (i.first==p) continue; ed[i.second].to=i.first; dep[i.first]=dep[x]+1; sp[i.first][0]=x; dfs(i.first,x); } out[x]=cnt; } void sparce_table() { for (int i=1;(1<<i)<=n;i++) { for (int j=1;j<=n;j++) { if (sp[j][i-1]==-1) sp[j][i]=-1; else sp[j][i]=sp[sp[j][i-1]][i-1]; } } } void precomp() { cnt=dep[1]=0; memset(sp,-1,sizeof(sp)); dfs(1,-1); sparce_table(); int cur_road; for (int i=1;i<=m;i++) { cin >> cur_road >> p[i].c; p[i].subt=ed[cur_road].to; } sort(p+1,p+m+1); cnt=0; root[0]=build_tree(1,n); for (int i=1;i<=m;i++) { root[i]=update(root[i-1],1,n,in[p[i].subt],out[p[i].subt],p[i].c); } } long long check(int curr, int s, int t, int lca, int type) { return query(curr,1,n,in[s],type)+query(curr,1,n,in[t],type)-2ll*query(curr,1,n,in[lca],type); } int find_lca(int a, int b) { if (dep[a]<dep[b]) swap(a,b); int st=18; while (st>=0) { if (sp[a][st]!=-1 && dep[sp[a][st]]>dep[b]) a=sp[a][st]; st--; } if (a!=b) a=sp[a][0]; if (a==b) return a; st=18; while (st>=0) { if (sp[a][st]!=-1 && sp[b][st]!=-1 && sp[a][st]!=sp[b][st]) { a=sp[a][st]; b=sp[b][st]; } st--; } if (a!=b) a=sp[a][0]; return a; } long long solve(int s, int t, long long gold, long long silver) { int l, r, mid; int lca=find_lca(s,t); l=0; r=m; while (l<=r) { mid=(l+r)/2; if (check(root[mid],s,t,lca,0)<=silver) l=mid+1; else r=mid-1; } long long mi=check(root[m],s,t,lca,1)-check(root[r],s,t,lca,1); if (mi<=gold) return gold-mi; return -1; } int main () { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n >> m >> q; for (int i=1;i<=n-1;i++) { cin >> ed[i].a >> ed[i].b; v[ed[i].a].push_back({ed[i].b,i}); v[ed[i].b].push_back({ed[i].a,i}); } precomp(); int s, t; long long gold, silver; for (int i=0;i<q;i++) { cin >> s >> t >> gold >> silver; cout << solve(s,t,gold,silver) << endl; } 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...