#include <bits/stdc++.h>
using namespace std;
#define int long long
struct dataS{
// now is bit
private:
vector<int> tree;
int N;
int query(int idx){
int ans = 0;
for(int i = idx;i >= 1;i -= i&-i){
ans += tree[i];
}
return ans;
}
public:
dataS(int iN){
N = iN;
tree.resize(N+1);
}
void modify(int idx,int dv){
for(int i = idx;i <= N;i += i&-i){
tree[i] += dv;
}
}
int query(int u,int v){
if(u > v)swap(u,v);
return query(v)-query(u);
}
};
// ===== hld ====
vector<vector<int>> edges;
vector<int> sz,par,dep,hson,rdn,top;
int dfs1(int cur,int p,int cdep){
par[cur] = p;
dep[cur] = cdep;
int csz = 1;
int maxSz = 0;
int maxIdx = -1;
for(auto nxt:edges[cur]){
if(nxt == p)continue;
int nsz = dfs1(nxt,cur,cdep+1);
if(nsz > maxSz){
maxSz = nsz;
maxIdx = nxt;
}
csz += nsz;
}
hson[cur] = maxIdx;
return csz;
}
int gt = 1;
void dfs2(int cur,int p){
// dfs child first
rdn[cur] = gt;
gt++;
if(hson[cur] != -1){
top[hson[cur]] = top[cur];
dfs2(hson[cur],cur);
}
for(auto nxt:edges[cur]){
if(nxt == p)continue;
if(nxt == hson[cur])continue;
top[nxt] = nxt;
dfs2(nxt,cur);
}
}
int hld_q(int u,int v,dataS& bit){
int ans = 0;
while(top[u] != top[v]){
// cout << u << " " << v << endl;
if(dep[top[u]] > dep[top[v]]){
// lift up u
ans += bit.query(rdn[top[u]]-1,rdn[u]);// -1 because top[u]'s parent consider
u = par[top[u]];
}else{
ans += bit.query(rdn[top[v]]-1,rdn[v]);// -1 because top[u]'s parent consider
v = par[top[v]];
}
}
ans += bit.query(rdn[u],rdn[v]);
return ans;
}
void hld_m(int u,int v,int dv,dataS& bit){// modify in child
if(par[u] == v){
// modify u
// cout << "modify" << rdn[u] << endl;
bit.modify(rdn[u],dv);
}else{
// modify v
// cout << "modify" << rdn[v] << endl;
bit.modify(rdn[v],dv);
}
}
signed main(){
cin.tie(0);
ios_base::sync_with_stdio(0);
//start here
int N,C,Q;
cin >> N >> C >> Q;
// ==== input tree ===
edges.resize(N+1);
vector<array<int,2>> edgeUV;
for(int i = 0;i < N-1;i++){
int a,b;
cin >> a >> b;
edges[a].push_back(b);
edges[b].push_back(a);
edgeUV.push_back({a,b});
}
sz = par = dep = hson = rdn = top = vector<int>(N+1,0);
dfs1(1,-1,0);
top[1] = 1;
dfs2(1,-1);
// for(int i = 1;i <= N;i++)cout << rdn[i] << " ";cout << endl;
// for(int i = 1;i <= N;i++)cout << top[i] << " ";cout << endl;
// ==== input checkPoint ====
vector<array<int,3>> checkP;// cost,u,v
for(int i = 0;i < C;i++){
int loc,cost;
cin >> loc >> cost;
loc--;
checkP.push_back({cost,edgeUV[loc][0],edgeUV[loc][1]});
}
// ===== query input offline ====
vector<array<int,5>> qry;
for(int i = 0;i < Q;i++){
int u,v,g,s;
cin >> u >> v >> g >> s;
qry.push_back({u,v,g,s,i});
}
// ==== sort CheckPoint ====
sort(checkP.begin(),checkP.end());
vector<int> ans(Q);
dataS silver(N+1);
dataS gold(N+1);
dataS change(N+1);
for(auto [cost,a,b]:checkP){
// gold.modify(a,b,1);
hld_m(a,b,1,gold);
}
// for(int u = 1;u <= N;u++){
// for(int v = u;v <= N;v++){
// cout << u << " " << v << ":" << hld_q(u,v,gold) << endl;
// }
// }
// cout << hld_q(1,3,gold) << endl;
// return 0;
auto whole = [&](int l,int r,vector<array<int,5>> cq,auto whole){
if(l > r){
// answer queries;
for(auto [u,v,g,s,idx]:cq){
// cout << idx << ":" << gold.query(u,v) << " " << change.query(u,v) << endl;
// cout << idx << ":" << hld_q(u,v,gold) << " " << hld_q(u,v,change) << endl;
// ans[idx] = max(-1LL,g-(gold.query(u,v)-change.query(u,v)));
ans[idx] = max(-1LL,g-(hld_q(u,v,gold)-hld_q(u,v,change)));
}
return;
}
// put half queries in
int m = (l+r)/2;
for(int i = l;i <= m;i++){
// ! full point change to hld
// change.modify(checkP[i][1],checkP[i][2],1);
// silver.modify(checkP[i][1],checkP[i][2],checkP[i][0]);
hld_m(checkP[i][1],checkP[i][2],1,change);
hld_m(checkP[i][1],checkP[i][2],checkP[i][0],silver);
}
vector<array<int,5>> ql,qr;
for(auto [u,v,g,s,idx]:cq){
// bool ok = silver.query(u,v) <= s;
bool ok = hld_q(u,v,silver) <= s;
if(ok){
qr.push_back({u,v,g,s,idx});
}else{
ql.push_back({u,v,g,s,idx});
}
}
whole(m+1,r,qr,whole);
// remove;
for(int i = l;i <= m;i++){
// ! full point change to hld
// change.modify(checkP[i][1],checkP[i][2],-1);
// silver.modify(checkP[i][1],checkP[i][2],-checkP[i][0]);
hld_m(checkP[i][1],checkP[i][2],-1,change);
hld_m(checkP[i][1],checkP[i][2],-checkP[i][0],silver);
}
whole(l,m-1,ql,whole);
};
whole(0,C-1,qry,whole);
for(auto i:ans)cout << i << "\n";
}
// 整體2分
# | 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... |