来自学长的馈赠7 社论
count
可以发现若能分为 组当且仅当:
- .
- 每个子树的大小为 的倍数的恰有 个 .
证明可以和 Sakura 交流一下,这边只会感性理解 .
于是直接维护,需要精细实现 .
序列
首先给所有数 减去 ,于是答案就是最长不下降子序列长度 .
证明大概就是 .
时间复杂度 .
最远点对
线段树维护 dis 最大的两个端点,合并的时候枚举 6 种可能合并 .
LCA 可以树剖做,这样线段树建树大概是 .
查询的时候查一下 查一下 然后 4 种情况讨论即可 .
正确性问 Eafoo .
Code
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
const int N = 123456, LgN = __lg(N), INF = 0x3f3f3f3f;
vector<pii> g[N];
inline void addedge(int u, int v, ll w){g[u].emplace_back(make_pair(v, w));}
inline void ade(int u, int v, ll w){addedge(u, v, w); addedge(v, u, w);}
int n, q;
namespace HLD
{
int fa[N], dep[N], siz[N], son[N], top[N], dfn[N], rnk[N], dis[N], cc;
void dfs1(int u)
{
siz[u] = 1;
for (auto e : g[u])
{
int v = e.first, w = e.second;
if (fa[u] == v) continue;
dep[v] = dep[u] + 1; dis[v] = dis[u] + w;
fa[v] = u;
dfs1(v);
siz[u] += siz[v];
if (!son[u]|| (siz[v] > siz[son[u]])) son[u] = v;
}
}
void dfs2(int u, int t)
{
top[u] = t;
rnk[++cc] = u; dfn[u] = cc;
if (!son[u]) return ;
dfs2(son[u], t);
for (auto e : g[u])
if ((e.first != son[u]) && (e.first != fa[u])) dfs2(e.first, e.first);
}
inline int lca(int u, int v)
{
while (top[u] != top[v])
{
if (!u || !v) return 0;
if (dep[top[u]] > dep[top[v]]) u = fa[top[u]];
else v = fa[top[v]];
}
return dep[u] > dep[v] ? v : u;
}
inline int dist(int u, int v){return dis[u] + dis[v] - 2 * dis[lca(u, v)];}
}
struct SMT
{
#define ls u << 1
#define rs u << 1 | 1
#define mid ((l + r) >> 1)
struct Node{int u, l, r, L, R;}tr[N << 2];
inline static Node merge(const Node& a, const Node& b)
{
int p1 = a.L, p2 = a.R, p3 = b.L, p4 = b.R, maxn = 0; Node ans;
auto _ = [&](int a, int b){int __ = HLD :: dist(a, b); if (__ > maxn){maxn = __; ans.L = a; ans.R = b;}};
_(p1, p2); _(p1, p3); _(p1, p4); _(p2, p3); _(p2, p4); _(p3, p4);
return ans;
}
inline void pushup(int u){Node _ = merge(tr[ls], tr[rs]); tr[u].L = _.L; tr[u].R = _.R;}
inline void build(int u, int l, int r)
{
tr[u].l = l; tr[u].r = r;
if (l == r){tr[u].L = tr[u].R = l; return ;}
build(ls, l, mid); build(rs, mid+1, r);
pushup(u);
}
inline Node query(int u, int L, int R)
{
int l = tr[u].l, r = tr[u].r;
if ((L <= l) && (r <= R)) return tr[u];
if ((L <= mid) && (R > mid)) return merge(query(ls, L, R), query(rs, L, R));
if (L <= mid) return query(ls, L, R);
return query(rs, L, R);
}
#undef mid
#undef rs
#undef ls
}T;
int main()
{
scanf("%d", &n);
for (int i=1, u, v, w; i<n; i++){scanf("%d%d%d", &u, &v, &w); ade(u, v, w);}
HLD :: dfs1(1); HLD :: dfs2(1, 1);
T.build(1, 1, n);
scanf("%d", &q); int a, b, c, d;
while (q--)
{
scanf("%d%d%d%d", &a, &b, &c, &d);
auto A = T.query(1, a, b), B = T.query(1, c, d);
printf("%d\n", max({HLD :: dist(A.L, B.L), HLD :: dist(A.L, B.R), HLD :: dist(A.R, B.L), HLD :: dist(A.R, B.R)}));
}
return 0;
}
春节十二响
考虑一条链的情况,我们将 点左右的左链 和右链 排序,只需要贪心的把内存占用排名相同的选上即可,正确性显然 .
于是推广到任意树,对于每个点用一个堆维护一下内存占用,合并即可每次取堆顶弹出,剩余的单算 .
分治,我们只需要把每个子树的答案合并,考虑启发式合并,可以证明时间复杂度为 .
Code
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int, int> pii;
const int N = 1e6 + 1;
vector<int> g[N];
inline void addedge(int u, int v){g[u].emplace_back(v);}
inline void ade(int u, int v){addedge(u, v); addedge(v, u);}
int n, a[N];
priority_queue<ll> q[N];
vector<int> now;
inline void merge(int x, int y)
{
if (q[x].size() < q[y].size()) swap(q[x], q[y]);
while (!q[y].empty())
{
now.emplace_back(max(q[x].top(), q[y].top()));
q[x].pop(); q[y].pop();
}
for (auto it = now.rbegin(); it != now.rend(); ++it) q[x].push(*it);
now.clear();
}
void dfs(int u)
{
for (int v : g[u]){dfs(v); merge(u, v);}
q[u].push(a[u]);
}
int main()
{
scanf("%d", &n);
for (int i=1; i<=n; i++) scanf("%d", a+i);
for (int i=2, f; i<=n; i++) scanf("%d", &f), addedge(f, i);
dfs(1);
ll ans = 0;
while (!q[1].empty()){ans += q[1].top(); q[1].pop();}
printf("%lld\n", ans);
return 0;
}
以下是博客签名,正文无关
本文来自博客园,作者:yspm,转载请注明原文链接:https://www.cnblogs.com/CDOI-24374/p/16538863.html
版权声明:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议(CC BY-NC-SA 4.0)进行许可。看完如果觉得有用请点个赞吧 QwQ
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】