P9755 [CSP-S 2023] 种树
思路
这道题看到所有c为0,那么所有树的生长时间就是确定的,那么就可以贪心的把生长时间长的先种上。
那么对于c不为0,我们考虑二分答案,二分完答案后,我们考虑对于每个树把他最晚种上的合法时间算出来,然后按照上面的贪心做就做完了。
不要写了一个函数不调用啊
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
ll a[100005], b[100005], c[100005];
inline __int128 sol(ll x, ll l, ll r)
{
__int128 ret = (r - l + 1) * b[x];
__int128 res = (r - l + 1);
res *= l + r;
res /= 2;
res *= c[x];
if (c[x] == 0)
{
return ret;
}
if (c[x] > 0)
{
return ret + res;
}
ll im = (1 - b[x]) / c[x];
if (im < l)
{
return r - l + 1;
}
if (im > r)
{
return ret + res;
}
ret = (im - l + 1) * b[x];
res = (im - l + 1);
res *= l + im;
res /= 2;
res *= c[x];
res += r - im;
return ret + res;
}
int fa[100005];
vector<int> g[100005];
void dfs(ll x, ll f)
{
fa[x] = f;
for (auto v : g[x])
{
if (v == f)
{
continue;
}
dfs(v, x);
}
}
void write(__int128 x)
{
if (x < 10)
{
ll t = x % 10;
cout << t;
return;
}
ll t = x % 10;
write(x / 10);
cout << t;
}
int n;
int t[100005], p[100005];
bool cmp(int x, int y)
{
return t[x] < t[y];
}
int dis[100005];
inline bool chk(ll x)
{
// cout << x << "\n";
for (int i = 1; i <= n; i++)
{
if (sol(i, 1, x) < a[i])
{
return 0;
}
dis[i] = -1;
p[i] = i;
ll l = 1, r = n, rt = 0;
while (l <= r)
{
ll mid = (l + r) >> 1;
if (sol(i, mid, x) >= a[i])
{
rt = mid;
l = mid + 1;
}
else
{
r = mid - 1;
}
}
t[i] = rt;
// cout << t[i] << " \n"[i == n];
}
// for (int i = 1; i <= n; i++)
// {
// write(sol(i, t[i], x));
// cout << " \n"[i == n];
// }
sort(p + 1, p + n + 1, cmp);
dis[0] = 0;
ll ntm = 0;
for (int i = 1; i <= n; i++)
{
ll nid = p[i];
vector<int> v;
while (dis[nid] == -1)
{
v.push_back(nid);
nid = fa[nid];
}
reverse(v.begin(), v.end());
for (auto j : v)
{
// cout << j << " " << ntm + 1 << "\n";
dis[j] = ++ntm;
}
}
for (int i = 1; i <= n; i++)
{
// cout << dis[i] << " \n"[i == n];
if (dis[i] > t[i])
{
return 0;
}
}
return 1;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> a[i] >> b[i] >> c[i];
}
for (int i = 1; i < n; i++)
{
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
int l = 0, r = 1e9;
int ans = -1;
while (l <= r)
{
int mid = (l + r) >> 1;
if (chk(mid))
{
r = mid - 1;
ans = mid;
}
else
{
l = mid + 1;
}
}
cout << ans << "\n";
return 0;
}

浙公网安备 33010602011771号