社区讨论
24pts,悬赏20rmb求调
P11324【MX-S7-T2】「SMOI-R2」Speaker参与者 3已保存回复 8
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @m416wcpx
- 此快照首次捕获于
- 2024/11/28 18:46 去年
- 此快照最后确认于
- 2025/11/04 13:44 4 个月前
rt,dp思路是第一次dfs求出x到以x为根的子树的最优方案,第二次与父亲比较求出x到所有点的最优方案,线段树维护区间最大值
看了讨论区里关于24pts的警示后人,感觉按照这个思路处理并不会出现该问题,实际上我没过的点也和那个楼主不一样,故求大佬帮忙看一下
CPP#include <bits/stdc++.h>
#define ll long long
#define lson(X) ((X) << 1)
#define rson(X) (((X) << 1) | 1)
#define mid ((l + r) >> 1)
#define maxn 200010
using namespace std;
#define writeln(X) write(X), putchar('\n')
template < typename T >
inline void read(T &X)
{
X = 0; bool f = false; char ch = getchar();
while (!isdigit(ch)) {f |= ch == '-'; ch = getchar();}
while (isdigit(ch)) {X = (X * 10) + (ch ^ 48); ch = getchar();}
X = f ? -X : X;
}
template < typename T >
inline void write(T X)
{
if (X == 0) {putchar('0'); return;}
if (X < 0) {putchar('-'); X = -X;}
static char cnt = 0, num[20];
while (X) *(num + cnt++) = X % 10, X /= 10;
while (cnt) putchar(*(num + --cnt) ^ 48);
return;
}
struct side {int to, nxt, dis;} sidelist[maxn << 1];
int head[maxn], sidecnt;
inline void buildside(const int &u, const int &v, const int &w) {sidelist[++sidecnt] = {v, head[u], w}; head[u] = sidecnt;}
int n, q;
ll c[maxn];
ll d[maxn];
int siz[maxn], heavy[maxn], fa[maxn], dep[maxn];
void dfs1(const int &x)
{
siz[x] = 1;
for (int i = head[x]; i; i = sidelist[i].nxt)
{
int to = sidelist[i].to, dis = sidelist[i].dis;
if (to == fa[x]) continue;
d[to] = d[x] + dis; fa[to] = x; dep[to] = dep[x] + 1;
dfs1(to);
siz[x] += siz[to];
if (siz[to] > siz[heavy[x]]) heavy[x] = to;
}
}
int lin[maxn], dfn[maxn];
int dfncnt;
void dfs2(const int &x)
{
dfn[x] = ++dfncnt;
if (heavy[x]) {lin[heavy[x]] = lin[x]; dfs2(heavy[x]);}
for (int i = head[x]; i; i = sidelist[i].nxt)
{
int to = sidelist[i].to;
if (to == fa[x] || to == heavy[x]) continue;
lin[to] = to; dfs2(to);
}
}
ll dp[maxn];
void dfs3(const int &x)
{
dp[x] = c[x];
for (int i = head[x]; i; i = sidelist[i].nxt)
{
int to = sidelist[i].to, dis = sidelist[i].dis;
if (to == fa[x]) continue;
dfs3(to); dp[x] = max(dp[x], dp[to] - 2ll * dis);
}
}
void dfs4(const int &x)
{
for (int i = head[x]; i; i = sidelist[i].nxt)
{
int to = sidelist[i].to;
if (to == fa[x]) continue;
dfs4(to);
}
if (fa[x]) dp[x] = max(dp[x], dp[fa[x]] - 2ll * (d[x] - d[fa[x]]));
}
inline int LCA(int x, int y)
{
if (dep[lin[x]] > dep[lin[y]]) swap(x, y);
while (lin[x] != lin[y])
{
y = fa[lin[y]];
if (dep[lin[x]] > dep[lin[y]]) swap(x, y);
}
if (dep[x] > dep[y]) swap(x, y);
return x;
}
int seg[maxn << 2];
void add(const int &x, const int &l, const int &r, const int &loc, const int &val)
{
if (l == r) {seg[x] = val; return;}
if (loc <= mid) add(lson(x), l, mid, loc, val);
else add(rson(x), mid + 1, r, loc, val);
seg[x] = max(seg[lson(x)], seg[rson(x)]);
}
ll query(const int &x, const int &l, const int &r, const int &lx, const int &rx)
{
if (l >= lx && r <= rx) {return seg[x];}
ll res = -0x3f3f3f3f3f3f3f3f;
if (mid >= lx) res = max(res, query(lson(x), l, mid, lx, rx));
if (mid + 1 <= rx) res = max(res, query(rson(x), mid + 1, r, lx, rx));
return res;
}
inline ll treequery(int x, const int &y)
{
ll res = -0x3f3f3f3f3f3f3f3f;
while (lin[x] != lin[y])
{
res = max(res, query(1, 1, n, dfn[lin[x]], dfn[x]));
x = fa[lin[x]];
}
res = max(res, query(1, 1, n, dfn[y], dfn[x]));
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("P11324.in", "r", stdin);
freopen("P11324.out", "w", stdout);
#endif
memset(seg, -0x3f, sizeof(seg));
read(n); read(q);
for (int i = 1; i <= n; ++i) read(c[i]);
for (int i = 1; i < n; ++i)
{
int u, v, w;
read(u); read(v); read(w);
buildside(u, v, w); buildside(v, u, w);
}
dep[1] = 1; dfs1(1); lin[1] = 1; dfs2(1); dfs3(1); dfs4(1);
for (int i = 1; i <= n; ++i) add(1, 1, n, dfn[i], dp[i]);
for (int i = 1; i <= q; ++i)
{
int x, y;
read(x); read(y);
int l = LCA(x, y);
writeln(c[x] + c[y] - (d[x] + d[y] - 2 * d[l]) + max(treequery(x, l), treequery(y, l)));
}
return 0;
}
回复
共 8 条回复,欢迎继续交流。
正在加载回复...