社区讨论
2log 做法求卡常
P9755[CSP-S 2023] 种树参与者 4已保存回复 7
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 7 条
- 当前快照
- 1 份
- 快照标识符
- @m1z8737m
- 此快照首次捕获于
- 2024/10/08 00:27 去年
- 此快照最后确认于
- 2025/11/04 17:40 4 个月前
rt,真的卡不动了
CPP#include <cstdio>
#include <algorithm>
#include <string.h>
using namespace std;
#define lint __int128
const int N = 1e5 + 5;
int n, u, v, fa[N], p[N], head[N], tot, s[N], dep[N]; // s[u]: 节点 u 最晚在 i 时刻被种树
lint a[N], b[N], c[N];
bool vis[N];
/*
max(b[i] + d * c[i], 1) + max(b[i] + (d + 1) * c[i], 1) + ... + (b[i] + t * c[i], 1) >= a[i]
*/
struct edge
{
int to, nxt;
} e[N << 1];
inline void addedge(int u, int v)
{
e[++tot] = {v, head[u]};
head[u] = tot;
}
inline lint ceildiv(lint x, lint y)
{
return x / y + (x % y != 0);
}
inline lint floordiv(lint x, lint y)
{
return x / y;
}
/*
b[i] + tu * c[i]
b[i] + t * c[i]
*/
bool judge(int i, int d, int t)
{
lint h, tu;
if(!c[i]) h = b[i] * (t - d + 1);
else
{
// tu 表示 >= 1 与 <= 1 的转折点
/*
b[i] + tu * c[i] >= 1
tu * c[i] >= 1 - b[i]
tu >= (1 - b[i]) / c[i] (c[i] > 0)
tu <= (1 - b[i]) / c[i] (c[i] < 0)
*/
if(c[i] > 0)
{
tu = max((lint) d, ceildiv(-b[i] + 1, c[i]));
h = tu > t ? t - d + 1 : (tu - d) + ((b[i] + tu * c[i]) + (b[i] + t * c[i])) * (t - tu + 1) / 2;
}
else
{
tu = min((lint) t, floordiv(-b[i] + 1, c[i]));
h = tu < d ? t - d + 1 : ((b[i] + d * c[i]) + (b[i] + tu * c[i])) * (tu - d + 1) / 2 + (t - tu);
}
}
return (h >= a[i]);
}
inline int update(int u)
{
if(vis[u] || !u) return 0;
vis[u] = 1;
return update(fa[u]) + 1;
}
inline bool cmp(int x, int y)
{
return s[x] < s[y];
}
bool check(int t)
{
memset(vis, 0, sizeof vis);
for(int i = 1; i <= n; i++)
{
int L = 1, R = t, pt;
if(!judge(i, 1, t)) return 0;
while(L <= R)
{
int mid = (L + R) >> 1;
if(judge(i, mid, t)) pt = mid, L = mid + 1;
else R = mid - 1;
}
s[i] = pt;
if(s[i] < dep[i]) return 0;
}
sort(p + 1, p + n + 1, cmp);
int cnt = 0;
for(int i = 1; i <= n; i++)
{
cnt += update(p[i]);
if(cnt > s[p[i]]) return 0;
}
return 1;
}
void dfs(int u)
{
for(int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if(v != fa[u]) dep[v] = dep[u] + 1, fa[v] = u, dfs(v);
}
return;
}
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++) p[i] = i;
for(int i = 1; i <= n; i++)
scanf("%lld %lld %lld", &a[i], &b[i], &c[i]);
for(int i = 1; i < n; i++)
{
scanf("%d %d", &u, &v);
addedge(u, v);
addedge(v, u);
}
dfs(1);
int l = n, r = 1e9, ans = n;
while(l <= r)
{
int mid = (l + r) >> 1;
if(check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d", ans);
return 0;
}
回复
共 7 条回复,欢迎继续交流。
正在加载回复...