이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
#define endl '\n'
const int MAXN=1e5+10;
const int LOG=20;
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;
int active;
int l, r;
};
vector <pair <int,int> > v[MAXN];
Checkpoint p[MAXN];
Edge ed[MAXN];
Node tree[4*MAXN*LOG];
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;
sp[1][0]=-1;
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,p+m);
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=17;
while (st>=0) {
if (dep[sp[a][st]]>dep[b]) a=sp[a][st];
st--;
}
if (a!=b) a=sp[a][0];
if (a==b) return a;
st=17;
while (st>=0) {
if (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;
}
int 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, 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 time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |