이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
#define fastio ios::sync_with_stdio(false), cin.tie(0);
#pragma GCC optimize("Ofast")
#define pb push_back
#define eb emplace_back
#define f first
#define s second
#define int long long
const int maxn = 1e5 + 5;
const int INF = 1e9 + 7;
vector<int> adj[maxn];
pll road[maxn];
int sz[maxn], dep[maxn], id[maxn], loc[maxn], par[maxn];
int head[maxn];
int cnt = 0;
int n, m, q;
void dfs(int pos, int prev){
if(prev != -1) adj[pos].erase(find(adj[pos].begin(), adj[pos].end(), prev));
sz[pos] = 1;
for(auto &x : adj[pos]){
dep[x] = dep[pos] + 1;
par[x] = pos;
dfs(x, pos);
if(sz[x] > sz[adj[pos][0]]) swap(x, adj[pos][0]);
}
}
void decompose(int pos, int h){
head[pos] = h;
id[pos] = ++cnt, loc[cnt] = pos;
for(auto x : adj[pos]){
if(x == adj[pos][0]) decompose(x, h);
else decompose(x, x);
}
}
struct info{
int s, t, x, y, id;
info(){}
info(int _s, int _t, int _x, int _y, int _id) : s(_s), t(_t), x(_x), y(_y), id(_id){}
};
pll st[maxn * 4];
void upd(int pos, int val, int v = 1, int l = 0, int r = maxn - 1){
st[v].f += val, st[v].s += (val > 0 ? 1 : -1);
if(l == r){
return;
}
int m = (l + r) / 2;
if(pos <= m) upd(pos, val, v * 2, l, m);
else upd(pos, val, v * 2 + 1, m + 1, r);
}
pll operator + (pll a, pll b){
return pll(a.f + b.f, a.s + b.s);
}
pll qry(int l, int r, int v = 1, int L = 0, int R = maxn - 1){
if(l > R || r < L) return {0, 0};
if(l <= L && r >= R) return st[v];
int m = (L + R) / 2;
return qry(l, r, v * 2, L, m) + qry(l, r, v * 2 + 1, m + 1, R);
}
pll solve(int a, int b){
pll ret = {0, 0};
while(head[a] != head[b]){
if(dep[head[a]] > dep[head[b]]) swap(a, b);
ret = ret + qry(id[head[b]], id[b]);
b = par[head[b]];
}
if(dep[a] > dep[b]) swap(a, b);
ret = ret + qry(id[a] + 1, id[b]);
return ret;
}
pll lok[maxn]; // 剛好可以 max. amount of gold coins
pll bad[maxn]; // 剛好不行
void bs(vector<pll> a, vector<info> rng, int l, int r, vector<pll> ax = vector<pll>(0)){
if(!rng.size()) return;
// cout<<"bs : "<<l<<" "<<r<<"\n";
if(l + 1 == r){
for(auto [s, t, x, y, id] : rng){
// auto [cnt, ttl] = solve(s, t);
lok[id] = solve(s, t);
continue;
// cout<<"end "<<id<<" : "<<l<<", ";
// cout<<cnt<<" "<<ttl<<"\n";
// if(cnt > y) ans[id] = -INF * INF;
// else ans[id] += ttl;
}
for(auto [c, p] : ax){
auto [x, y] = road[p];
if(dep[x] < dep[y]) swap(x, y);
upd(id[x], c);
}
for(auto [s, t, x, y, id] : rng){
bad[id] = solve(s, t);
continue;
}
for(auto [c, p] : ax){
auto [x, y] = road[p];
if(dep[x] < dep[y]) swap(x, y);
upd(id[x], -c);
}
return;
}
int m = (l + r) / 2;
vector<pll> a1, a2, nax;
for(auto [c, p] : a){
auto [x, y] = road[p];
if(dep[x] < dep[y]) swap(x, y);
if(c > m) a2.eb(c, p);
else{
a1.eb(c, p);
// cout<<"cur : "<<x<<" "<<y<<" "<<p<<"\n";
upd(id[x], c);
}
if(c == m) nax.eb(c, p);
}
vector<info> r1, r2;
for(auto [s, t, x, y, id] : rng){
auto [cnt, ttl] = solve(s, t);
// cout<<"get : "<<id<<" "<<x<<" "<<cnt<<" "<<ttl<<"\n";
if(y >= cnt) r2.pb(info(s, t, x, y, id));
else r1.pb(info(s, t, x, y, id));
}
bs(a2, r2, m, r, ax);
for(auto [c, p] : a1){
auto [x, y] = road[p];
if(dep[x] < dep[y]) swap(x, y);
upd(id[x], -c);
}
bs(a1, r1, l, m, nax);
}
int ans[maxn];
signed main(void){
fastio;
cin>>n>>m>>q;
for(int i = 0; i < n - 1; i++){
int a, b;
cin>>a>>b;
a--, b--;
adj[a].pb(b);
adj[b].pb(a);
road[i] = {a, b};
}
vector<pll> a(m);
for(int i = 0; i < m; i++){
cin>>a[i].s>>a[i].f;
a[i].s--;
}
sort(a.begin(), a.end());
vector<info> qry;
for(int i = 0; i < q; i++){
int s, t, x, y;
cin>>s>>t>>x>>y;
s--, t--;
qry.pb(info(s, t, x, y, i));
}
dfs(0, -1);
decompose(0, 0);
bs(a, qry, 0, INF);
for(int i = 0; i < m; i++){
auto [c, p] = a[i];
auto [b, d] = road[p];
if(dep[b] < dep[d]) swap(b, d);
upd(id[b], 1);
}
for(int i = 0; i < q; i++){
auto [s, t, x, y, id] = qry[i];
auto [c1, t1] = lok[i];
auto [c2, t2] = bad[i];
int cnt = (c2 - c1) / (t2 - t1);
int canuse = (y - c1) / cnt;
ans[i] += x + t1 + canuse - solve(s, t).s;
}
// for(int i = 0; i < n; i++) cout<<head[i]<<" "<<id[i]<<"\n";
for(int i = 0; i < q; i++){
cout<<(ans[i] < 0 ? -1 : ans[i])<<"\n";
}
}
/*
4 5 2
1 2
2 3
3 4
1 5
2 6
3 7
*/
# | 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... |