P5327 [ZJOI2019] 语言
1.P5327 [ZJOI2019] 语言
2.2024/04/05 多校集训B层-省选模拟53.2024/04/09 多校集训B层-省选模拟74.2024/04/13 多校集训B层-省选模拟85.2024/04/13 多校集训B层-NOIP模拟16.2024/04/15 多校集训B层-NOIP模拟37.UVA1316 Supermarket8.CF1787H Codeforces Scoreboard9.CF1463F Max Correct Set10.P2481 [SDOI2010] 代码拍卖会11.考试题解12.P5336 [THUSC2016] 成绩单13.[AGC035D] Add and Remove14.牛逼题15.String 做题记录16.树套树做题记录17.Atcoder 记录18.数论做题记录19.考试题解(题解纯享版)20.图论做题记录21.DS做题记录P5327 [ZJOI2019] 语言
最开始读错了题, 不然真有可能自己做出来, 遗憾。 考虑一个性质, 每次更新的语言都不一样, 那么这条链上的每个点对都可以互相进行贸易, 那么如果一个点在多条链上, 那它与这些链的所有人都可以贸易, 所以考虑点
我们有所有覆盖点
最小连通子树大小等于
考虑每个点都要算这玩意, 但是每次都暴力统计浪费了太多信息, 再想到哪些信息可以保留, 如果我们把路径加改成差分加子树和, 就可以从儿子继承信息, 并可以得出整个数的答案, 考虑差分可行性, 一条链
所以可做, 线段树合并即可。
码了一个多小时, 还借助了题解代码, 我真是fw
代码
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
#define int long long
int n, m, head[N], tot, rt[N];
struct Edge{ int to, next; }edge[N << 1];
void add(int x, int y) {
edge[++tot] = {y, head[x]}; head[x] = tot;
edge[++tot] = {x, head[y]}; head[y] = tot;
}
int dfn[N], tim, st[20][N], lg[N * 2] = {-1}, fa[N], dep[N], id[N * 2];
void dfs(int u, int pre) {
dfn[u] = ++tim, st[0][tim] = u, fa[u] = pre;
dep[u] = dep[pre] + 1, id[tim] = u;
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == pre) continue;
dfs(v, u);
st[0][++tim] = u;
}
}
void build_st() {
for (int i = 1; i <= lg[tim]; i++) {
for (int j = 1; j + (1 << i) - 1 <= tim; j++) {
int x = st[i - 1][j], y = st[i - 1][j + (1 << (i - 1))];
st[i][j] = dep[x] < dep[y] ? x : y;
}
}
}
int lca(int x, int y) {
if (x == 0 || y == 0) return 0;
x = dfn[x], y = dfn[y];
if (x > y) swap(x, y);
int k = lg[y - x + 1];
return dep[st[k][x]] < dep[st[k][y - (1 << k) + 1]] ? st[k][x] : st[k][y - (1 << k) + 1];
}
vector<int> del[N];
#define pb push_back
struct SegT{
struct Node{
int ls, rs, mx, mn, sum, is;
}t[N * 80];
int tot;
#define ls(p) (t[p].ls)
#define rs(p) (t[p].rs)
#define mid (l + r >> 1)
void pushup(int p) {
t[p].sum = t[ls(p)].sum + t[rs(p)].sum - dep[lca(id[t[ls(p)].mx], id[t[rs(p)].mn])];
t[p].mn = t[ls(p)].mn ? t[ls(p)].mn : t[rs(p)].mn;
t[p].mx = t[rs(p)].mx ? t[rs(p)].mx : t[ls(p)].mx;
}
void modify(int &p, int l, int r, int x, int y) {
if (!p) p = ++tot;
if (l == r) {
t[p].is += y;
if (t[p].is > 0) t[p].mn = t[p].mx = x, t[p].sum = dep[id[x]];
if (t[p].is <= 0) t[p].mn = t[p].mx = t[p].sum = 0;
return;
}
if (x <= mid) modify(ls(p), l, mid, x, y);
if (x > mid) modify(rs(p), mid + 1, r, x, y);
pushup(p);
}
int query(int p) { return t[p].sum - dep[lca(id[t[p].mn], id[t[p].mx])]; }
void merge(int &p1, int p2, int l, int r) {
if (!p1 || !p2) return p1 |= p2, void();
if (l == r) {
t[p1].is += t[p2].is;
if (t[p1].is > 0) t[p1].mn = t[p1].mx = l, t[p1].sum = dep[id[l]];
if (t[p1].is <= 0) t[p1].mn = t[p1].mx = t[p1].sum = 0;;
return;
}
merge(ls(p1), ls(p2), l, mid); merge(rs(p1), rs(p2), mid + 1, r);
pushup(p1);
}
}T;
int ans;
void work(int u, int pre) {
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (v == pre) continue;
work(v, u);
T.merge(rt[u], rt[v], 1, tim);
}
for (auto i : del[u]) T.modify(rt[u], 1, tim, dfn[i], -1);
ans += T.query(rt[u]);
}
signed main() {
scanf("%lld%lld", &n, &m);
for (int i = 1; i <= n * 2; i++) lg[i] = lg[i / 2] + 1;
for (int i = 1, x, y; i <= n - 1; i++) {
scanf("%lld%lld", &x, &y);
add(x, y);
}
dfs(1, 0); build_st();
for (int i = 1, u, v, _lca; i <= m; i++) {
scanf("%lld%lld", &u, &v); _lca = lca(u, v);
del[_lca].pb(u); del[_lca].pb(v);
del[fa[_lca]].pb(u); del[fa[_lca]].pb(v);
T.modify(rt[u], 1, tim, dfn[u], 1);
T.modify(rt[u], 1, tim, dfn[v], 1);
T.modify(rt[v], 1, tim, dfn[v], 1);
T.modify(rt[v], 1, tim, dfn[u], 1);
}
work(1, 0); printf("%lld", ans / 2);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App