This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long ll;
void speed()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
}
const ll maxn = 1e5 + 10;
struct checkpoll
{
ll p, c;
void read()
{
cin >> p >> c;
}
bool operator < (const checkpoll &t) const
{
return c < t.c;
}
} cp[maxn];
struct citizen
{
ll s, t, x, y;
void read()
{
cin >> s >> t >> x >> y;
}
} ct[maxn];
ll n, m, q;
vector < ll > adj[maxn];
pair < ll, ll > road[maxn];
void input()
{
cin >> n >> m >> q;
for (ll i = 1; i < n; i ++)
{
ll a, b;
cin >> a >> b;
road[i] = {a, b};
adj[a].push_back(b);
adj[b].push_back(a);
}
for (ll i = 1; i <= m; i ++)
cp[i].read();
for (ll i = 1; i <= q; i ++)
ct[i].read();
}
ll tin[maxn], tout[maxn], timer, occ[2 * maxn];
ll par[maxn], depth[maxn];
void euler_tour(ll v = 1, ll p = 0)
{
occ[++ timer] = v;
tin[v] = timer;
for (ll u : adj[v])
{
if (u == p)
continue;
depth[u] = depth[v] + 1;
par[u] = v;
euler_tour(u, v);
occ[++ timer] = v;
}
tout[v] = timer;
}
const ll maxlog = 20;
struct sparse_table
{
ll lg[2 * maxn], dp[maxlog][2 * maxn];
void build_sparse_table()
{
for (ll i = 1; i <= timer; i ++)
{
lg[i] = lg[i / 2] + 1;
dp[0][i] = occ[i];
}
for (ll j = 1; j < lg[timer]; j ++)
{
for (ll i = 1; i <= timer - (1 << j) + 1; i ++)
{
dp[j][i] = dp[j - 1][i + (1 << (j - 1))];
if (depth[dp[j - 1][i]] < depth[dp[j][i]])
dp[j][i] = dp[j - 1][i];
}
}
/**cout << "---------------" << endl;
for (ll j = 0; j < lg[timer]; j ++, cout << endl)
for (ll i = 1; i <= timer; i ++)
cout << dp[j][i] << " ";*/
}
ll lca_query(ll v, ll u)
{
ll l = tin[v], r = tin[u];
if (l > r)
swap(l, r);
ll len = lg[r - l + 1] - 1, lca = dp[len][r - (1 << len) + 1];
///cout << "lca " << v << " " << u << " " << l << " " << r << endl;
if (depth[dp[len][l]] < depth[lca])
lca = dp[len][l];
return lca;
}
};
sparse_table st;
struct fenwick
{
ll fen[2 * maxn];
void add(ll pos, ll val)
{
for (ll i = pos; i <= timer; i += (i & -i))
fen[i] += val;
}
ll sum(ll pos)
{
ll s = 0;
for (ll i = pos; i > 0; i -= (i & -i))
s += fen[i];
return s;
}
void range_update(ll left, ll right, ll val)
{
add(left, val);
add(right + 1, - val);
}
ll query(ll pos)
{
return sum(pos);
}
};
fenwick gold, silver;
pair < ll, ll > range[maxn];
vector < ll > upd[maxn];
ll binary_position(ll val)
{
ll left = 1, right = m;
while(left <= right)
{
ll mid = left + (right - left) / 2;
if (cp[mid].c <= val)
left = mid + 1;
else
right = mid - 1;
}
return right;
}
ll ans[maxn];
pair < ll, ll > avab[maxn];
void parallel_binary_search()
{
for (ll i = 1; i <= q; i ++)
{
range[i] = {0, 1e9 + 10};
}
for (ll i = 1; i < n; i ++)
{
if (depth[road[i].first] < depth[road[i].second])
swap(road[i].first, road[i].second);
}
/**for (ll i = 1; i <= m; i ++)
{
cout << road[cp[i].p].first << endl;
}*/
sort(cp + 1, cp + m + 1);
while(true)
{
bool done = true;
for (ll i = 0; i <= m; i ++)
upd[i].clear();
for (ll i = 1; i <= q; i ++)
{
if (range[i].first <= range[i].second)
{
done = false;
ll mid = (range[i].first + (range[i].second - range[i].first) / 2);
ll pos = binary_position(mid);
upd[pos].push_back(i);
}
}
if (done)
break;
//for (ll i = 1; i <= m; i ++)
// gold.range_update(tin[cp[i].p], tout[cp[i].p], 1);
/**cout << "-------------" << endl;
for (ll i = 1; i <= m; i ++)
cout << range[i].first << " " << range[i].second << endl;*/
for (ll i = 0; i <= m; i ++)
{
if (i != 0)
{
silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], cp[i].c);
}
for (ll idx : upd[i])
{
ll lca = st.lca_query(ct[idx].s, ct[idx].t);
ll val = silver.query(tin[ct[idx].s]) + silver.query(tin[ct[idx].t]);
val = val - 2 * silver.query(tin[lca]);
///co
///cout << idx << " : " << val << " -- " << lca << endl;
/**if (idx == 6)
{
cout << ct[idx].s << " " << ct[idx].t << " " << val << " " << lca << " " << i << endl;
}*/
ll mid = (range[idx].first + (range[idx].second - range[idx].first) / 2);
if (val > ct[idx].y)
range[idx].second = mid - 1;
else
range[idx].first = mid + 1;
}
}
for (ll i = 1; i <= m; i ++)
silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -cp[i].c);
}
for (ll i = 0; i <= m; i ++)
upd[i].clear();
for (ll i = 1; i <= q; i ++)
{
ll pos = binary_position(range[i].first);
upd[pos].push_back(i);
}
for (ll i = 1; i <= m; i ++)
{
gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], 1);
}
for (ll i = 0; i <= m; i ++)
{
if (i != 0)
{
silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], cp[i].c);
gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -1);
}
/**cout << "step" << endl;
cout << i << endl;
for (ll j = 1; j <= n; j ++)
cout << gold.query(tin[j]) << " ";
cout << endl;
cout << "order" << endl;
for (ll j = 1; j <= timer; j ++)
cout << occ[j] << " ";
cout << endl;*/
for (ll idx : upd[i])
{
ll lca = st.lca_query(ct[idx].s, ct[idx].t);
ll val = silver.query(tin[ct[idx].s]) + silver.query(tin[ct[idx].t]);
val = val - 2 * silver.query(tin[lca]);
ll min_gold = gold.query(tin[ct[idx].s]) + gold.query(tin[ct[idx].t]);
///cout << "gold " << min_gold << " " << gold.query(tinendl;
min_gold = min_gold - 2 * gold.query(tin[lca]);
//cout << idx << " : " << min_gold << " " << i << " lca " << lca << endl;
avab[idx].second = min_gold;
}
}
for (ll i = 1; i <= m; i ++)
silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -cp[i].c);
for (ll i = 0; i <= m; i ++)
upd[i].clear();
for (ll i = 1; i <= q; i ++)
{
ll pos = binary_position(range[i].second);
upd[pos].push_back(i);
}
for (ll i = 1; i <= m; i ++)
{
gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], 1);
}
for (ll i = 0; i <= m; i ++)
{
if (i != 0)
{
silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], cp[i].c);
gold.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -1);
}
/**cout << "step" << endl;
cout << i << endl;
for (ll j = 1; j <= n; j ++)
cout << gold.query(tin[j]) << " ";
cout << endl;
cout << "order" << endl;
for (ll j = 1; j <= timer; j ++)
cout << occ[j] << " ";
cout << endl;*/
for (ll idx : upd[i])
{
ll lca = st.lca_query(ct[idx].s, ct[idx].t);
ll val = silver.query(tin[ct[idx].s]) + silver.query(tin[ct[idx].t]);
val = val - 2 * silver.query(tin[lca]);
ll min_gold = gold.query(tin[ct[idx].s]) + gold.query(tin[ct[idx].t]);
///cout << "gold " << min_gold << " " << gold.query(tinendl;
min_gold = min_gold - 2 * gold.query(tin[lca]);
//cout << idx << " : " << min_gold << " " << i << " lca " << lca << endl;
ll to_fill = min_gold - avab[idx].second, cnt = range[idx].first;
ll cn = min(to_fill, (ct[idx].y - val) / cnt);
ll left_gold = ct[idx].x - min_gold + cn;
if (left_gold < 0)
left_gold = - 1;
ans[idx] = left_gold;
}
}
for (ll i = 1; i <= m; i ++)
silver.range_update(tin[road[cp[i].p].first], tout[road[cp[i].p].first], -cp[i].c);
for (ll i = 1; i <= q; i ++)
cout << ans[i] << endl;
}
void solve()
{
input();
euler_tour(1, 0);
st.build_sparse_table();
parallel_binary_search();
}
int main()
{
speed();
solve();
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... |