P5416 = UOJ 198 时空旅行 题解

news/2024/10/7 9:32:37/文章来源:https://www.cnblogs.com/laijinyi/p/18449773

Statement

一棵树,每个节点上有一个集合,每个儿子集合由父亲集合增加一个点 \((x_i,c_i)\) 或删除一个点得到。根节点集合为 \(\{(0,0,0,c_0)\}\)

多次询问,每次问 \(u\) 点的集合内,\(\min\{(x_i-x)^2+c_i\}\)

Solution

首先你认真读完题发现原题中 \(y,z\) 都是没用的

然后离线 DFS 一遍,问题变成加点,删点,问 \(\min_{i}(x_i-x)^2+c_i\)

化一下式子,变成 \(\displaystyle x^2+\min_{i}\{-2x_i\cdot x+x_i^2+c_i\}\)

于是考虑李超树,需要支持加直线、删直线,发现删不了。。。

于是线段树分治,考虑 DFS 序,一遍 DFS 可以找出所有直线的出现位置,做完了。

撤销可以直接撤销,当然你写可持久化李超树也没人拦着。


另一种方式:\(Ans_i=(x_i-x)^2+c_i\),要求 \(Ans_i\) 最小

化成:\(x_i^2+c_i=2x\cdot x_i+Ans_i-x^2\)

\(k=2x,b=Ans_i-x^2\),这是一个 \(y_i=kx_i+b\),每个点为 \((x_i,x_i^2+c_i)\),用 \(k=2x\) 来切这些点,要 \(b\) 最小

考虑维护下凸包,我们需要维护加点、删点

这可以直接平衡树维护,单 log

但是如果你不想写平衡树,那可以加个线段树分治。


发现这里的线段树分治,各节点之间没有顺序而言,意思就是我们可以任意顺序遍历他

而凸壳的维护很有优化前途,我们令 \(x\) 递增就可以线性插入、令询问斜率单增可以线性处理询问;凸包的归并也是线性的

于是我们对每个插入和询问都排一遍序就能同样做到 \(O(n\log n)\) 维护了。

Code 1

李超树,直接撤销

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define reo(i, j, k) for (int i = (j); i >= (k); --i)
typedef long long ll;char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 20], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1++)
#define putchar(x) ((O - obuf < (1 << 20)) ? (*O++ = x) : (fwrite(obuf, O - obuf, 1, stdout), O = obuf, *O++ = x))inline ll Read() {ll x = 0;int f = 1;char ch = getchar();for (; ch < 48 || ch > 57; ch = getchar()) if (ch == '-') f = 0;for (; 48 <= ch && ch <= 57; ch = getchar()) x = (x << 3) + (x << 1) + ch - 48;return f ? x : -x;
}
inline void Write(ll x) {if (!x) {putchar(48);} else {static int stk[50], tp;tp = 0;while (x) stk[++tp] = x % 10, x /= 10;while (tp) putchar(stk[tp--] + 48);}putchar('\n');
}const int N = 5e5 + 10, M = 2e7 + 10;
vector<pair<ll, int>> Quer[N];
vector<int> G[N];
ll ans[N], X[N];
int n, m, Xtot;
struct Planet {ll x, c;
} a[N];
struct Set {int op, id;
} b[N];
int Get(ll x) {return lower_bound(X + 1, X + Xtot + 1, x) - X;
}int tim, dfn[N], revdfn[N], sz[N];
vector<pair<int, int>> Add[N], Del[N];
void DFS1(int u) {dfn[u] = ++tim, revdfn[tim] = u, sz[u] = 1;for (int v : G[u]) {DFS1(v), sz[u] += sz[v];}if (b[u].op) {Add[b[u].id].push_back({dfn[u], dfn[u] + sz[u] - 1});} else {Del[b[u].id].push_back({dfn[u], dfn[u] + sz[u] - 1});}
}#define lc (u << 1)
#define rc ((u << 1) | 1)
#define mid ((l + r) >> 1)struct Line {ll k, b;
} line[N];
int tag[N << 2];
pair<int, int> Modif[M];
int Tim;
ll Val(int id, int x) {return (!id) ? (ll)1e18 : line[id].k * X[x] + line[id].b;
}
void Upd(int u, int l, int r, int id) {if (!tag[u]) return Modif[++Tim] = {u, tag[u]}, tag[u] = id, void();if (Val(id, mid) < Val(tag[u], mid)) Modif[++Tim] = {u, tag[u]}, swap(tag[u], id);if (Val(id, l) < Val(tag[u], l)) Upd(lc, l, mid, id);else if (Val(id, r) < Val(tag[u], r)) Upd(rc, mid + 1, r, id);
}
ll Qry(int u, int l, int r, int x) {if (l == r) return Val(tag[u], x);return min(Val(tag[u], x), (x <= mid) ? Qry(lc, l, mid, x) : Qry(rc, mid + 1, r, x));
}vector<int> Segments[N << 2];
void Ins(int u, int l, int r, int x, int y, int v) {if (y < l || r < x || x > y) return;if (x <= l && r <= y) return Segments[u].push_back(v);Ins(lc, l, mid, x, y, v), Ins(rc, mid + 1, r, x, y, v);
}
void Solve(int u, int l, int r) {int OriginTim = Tim;for (auto p : Segments[u]) {Upd(1, 1, Xtot, p);}if (l == r) {for (auto p : Quer[revdfn[l]]) ans[p.second] = p.first * p.first + Qry(1, 1, Xtot, Get(p.first));} else {Solve(lc, l, mid), Solve(rc, mid + 1, r);}reo(i, Tim, OriginTim + 1) {tag[Modif[i].first] = Modif[i].second;}Tim = OriginTim;
}#undef lc
#undef rc
#undef midint main() {n = Read(), m = Read(), a[1].c = Read(), b[1].op = 1, b[1].id = 1;rep(i, 2, n) {int op = Read(), fr = Read() + 1, id = Read() + 1, x;ll c;G[fr].push_back(i);if (op == 0) {x = Read(), Read(), Read(), c = Read(), a[id] = {x, c}, b[i] = {1, id};} else {b[i] = {0, id};}}rep(i, 1, m) {int s = Read();ll x0 = Read();Quer[++s].push_back({x0, i});X[++Xtot] = x0;}DFS1(1);rep(i, 1, n) {sort(Add[i].begin(), Add[i].end());sort(Del[i].begin(), Del[i].end());int pos = -1, R = Del[i].size();for (auto p : Add[i]) {int last = p.first;while (pos < R - 1 && Del[i][pos + 1].second <= p.second) {auto now = Del[i][++pos];Ins(1, 1, n, last, now.first - 1, i);last = now.second + 1;}Ins(1, 1, n, last, p.second, i);}}rep(i, 1, n) line[i] = {-2ll * a[i].x, a[i].x * a[i].x + a[i].c};sort(X + 1, X + Xtot + 1);Xtot = unique(X + 1, X + Xtot + 1) - X - 1;Solve(1, 1, n);rep(i, 1, m) Write(ans[i]);fwrite(obuf, O - obuf, 1, stdout);return 0;
}

Code 2

李超树,可持久化

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define reo(i, j, k) for (int i = (j); i >= (k); --i)
typedef long long ll;
const int N = 5e5 + 10, M = 2e7 + 10;
vector<pair<ll, int>> Quer[N];
vector<int> G[N];
ll ans[N], X[N];
int n, m, Xtot;
struct Planet {ll x, c;
} a[N];
struct Set {int op, id;
} b[N];
int Get(ll x) {return lower_bound(X + 1, X + Xtot + 1, x) - X;
}int tim, dfn[N], revdfn[N], sz[N];
vector<pair<int, int>> Add[N], Del[N];
void DFS1(int u) {dfn[u] = ++tim, revdfn[tim] = u, sz[u] = 1;for (int v : G[u]) {DFS1(v), sz[u] += sz[v];}if (b[u].op) {Add[b[u].id].push_back({dfn[u], dfn[u] + sz[u] - 1});} else {Del[b[u].id].push_back({dfn[u], dfn[u] + sz[u] - 1});}
}#define mid ((l + r) >> 1)struct Line {ll k, b;
} line[N];
struct Node {int lc, rc, tag;
} f[M];
int tot, rt[N << 2], Tot[N << 2];
ll Val(int id, int x) {return (!id) ? (ll)1e18 : line[id].k * X[x] + line[id].b;
}
void Build(int &u, int l, int r) {f[u = ++tot].tag = 0;if (l == r) return;Build(f[u].lc, l, mid), Build(f[u].rc, mid + 1, r);
}
void Upd(int &u, int l, int r, int id, int lim) {if (u <= lim) f[++tot] = f[u], u = tot;if (!f[u].tag) return f[u].tag = id, void();if (Val(id, mid) < Val(f[u].tag, mid)) swap(f[u].tag, id);if (Val(id, l) < Val(f[u].tag, l)) Upd(f[u].lc, l, mid, id, lim);else if (Val(id, r) < Val(f[u].tag, r)) Upd(f[u].rc, mid + 1, r, id, lim);
}
ll Qry(int u, int l, int r, int x) {if (l == r) return Val(f[u].tag, x);return min(Val(f[u].tag, x), (x <= mid) ? Qry(f[u].lc, l, mid, x) : Qry(f[u].rc, mid + 1, r, x));
}#define lc (u << 1)
#define rc ((u << 1) | 1)vector<int> Segments[N << 2];
void Ins(int u, int l, int r, int x, int y, int v) {if (y < l || r < x || x > y) return;if (x <= l && r <= y) return Segments[u].push_back(v);Ins(lc, l, mid, x, y, v), Ins(rc, mid + 1, r, x, y, v);
}
void Solve(int u, int l, int r, int fa = 0) {rt[u] = rt[fa];for (auto p : Segments[u]) {Upd(rt[u], 1, Xtot, p, Tot[fa]);}Tot[u] = tot;if (l == r) {for (auto p : Quer[revdfn[l]])ans[p.second] = p.first * p.first + Qry(rt[u], 1, Xtot, Get(p.first));} else {Solve(lc, l, mid, u), Solve(rc, mid + 1, r, u);}tot = Tot[fa];
}#undef lc
#undef rc
#undef midint main() {ios::sync_with_stdio(false), cin.tie(nullptr);cin >> n >> m >> a[1].c, b[1].op = 1, b[1].id = 1;rep(i, 2, n) {int op, fr, id, x, y, z;ll c;cin >> op >> fr >> id, ++fr, ++id, G[fr].push_back(i);if (op == 0) {cin >> x >> y >> z >> c, a[id] = {x, c}, b[i] = {1, id};} else {b[i] = {0, id};}}rep(i, 1, m) {int s;ll x0;cin >> s >> x0;Quer[++s].push_back({x0, i});X[++Xtot] = x0;}DFS1(1);rep(i, 1, n) {sort(Add[i].begin(), Add[i].end());sort(Del[i].begin(), Del[i].end());int pos = -1, R = Del[i].size();for (auto p : Add[i]) {int last = p.first;while (pos < R - 1 && Del[i][pos + 1].second <= p.second) {auto now = Del[i][++pos];Ins(1, 1, n, last, now.first - 1, i);last = now.second + 1;}Ins(1, 1, n, last, p.second, i);}}rep(i, 1, n) line[i] = {-2ll * a[i].x, a[i].x * a[i].x + a[i].c};sort(X + 1, X + Xtot + 1);Xtot = unique(X + 1, X + Xtot + 1) - X - 1;Build(rt[0], 1, Xtot), Tot[0] = tot;Solve(1, 1, n);rep(i, 1, m) cout << ans[i] << '\n';return 0;
}

Code 3

凸包

#include <bits/stdc++.h>
using namespace std;
#define rep(i, j, k) for (int i = (j); i <= (k); ++i)
#define reo(i, j, k) for (int i = (j); i >= (k); --i)
typedef long long ll;char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 20], *O = obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 20, stdin), p1 == p2) ? EOF : *p1++)
#define putchar(x) ((O - obuf < (1 << 20)) ? (*O++ = x) : (fwrite(obuf, O - obuf, 1, stdout), O = obuf, *O++ = x))inline ll Read() {ll x = 0;int f = 1;char ch = getchar();for (; ch < 48 || ch > 57; ch = getchar()) if (ch == '-') f = 0;for (; 48 <= ch && ch <= 57; ch = getchar()) x = (x << 3) + (x << 1) + ch - 48;return f ? x : -x;
}
inline void Write(ll x) {if (!x) {putchar(48);} else {static int stk[50], tp;tp = 0;while (x) stk[++tp] = x % 10, x /= 10;while (tp) putchar(stk[tp--] + 48);}putchar('\n');
}const int N = 5e5 + 10;
struct Query {int s, id;ll x, k;
} Quer[N];
vector<int> G[N];
ll ans[N];
int n, m;
struct Point {ll x, y;
} a[N];
struct Set {int op, id;
} b[N];int tim, dfn[N], revdfn[N], sz[N];
vector<pair<int, int>> Add[N], Del[N];
void DFS(int u) {dfn[u] = ++tim, revdfn[tim] = u, sz[u] = 1;for (int v : G[u]) {DFS(v), sz[u] += sz[v];}if (b[u].op) {Add[b[u].id].push_back({dfn[u], dfn[u] + sz[u] - 1});} else {Del[b[u].id].push_back({dfn[u], dfn[u] + sz[u] - 1});}
}#define lc (u << 1)
#define rc ((u << 1) | 1)
#define mid ((l + r) >> 1)struct Convex {vector<int> vec;int pos;void Insert(int u) {for (int p = (int)vec.size() - 1; p > 0 && (a[vec[p]].y - a[vec[p - 1]].y) * (a[u].x - a[vec[p]].x) >= (a[u].y - a[vec[p]].y) * (a[vec[p]].x - a[vec[p - 1]].x); --p, vec.pop_back());vec.push_back(u);}ll Query(ll k) {if (vec.empty()) return 1e18;for (; pos < (int)vec.size() - 1 && a[vec[pos + 1]].y - a[vec[pos]].y < k * (a[vec[pos + 1]].x - a[vec[pos]].x); ++pos);return a[vec[pos]].y - k * a[vec[pos]].x;}
} Conv[N << 2];void Ins(int u, int l, int r, int x, int y, int v) {if (y < l || r < x || x > y) return;if (x <= l && r <= y) return Conv[u].Insert(v);Ins(lc, l, mid, x, y, v), Ins(rc, mid + 1, r, x, y, v);
}
ll Qry(int u, int l, int r, int x, ll k) {if (l == r) return Conv[u].Query(k);return min(Conv[u].Query(k), x <= mid ? Qry(lc, l, mid, x, k) : Qry(rc, mid + 1, r, x, k));
}#undef lc
#undef rc
#undef midint main() {n = Read(), m = Read(), a[1].y = Read(), b[1].op = 1, b[1].id = 1;rep(i, 2, n) {int op = Read(), fr = Read() + 1, id = Read() + 1;ll x, c;G[fr].push_back(i);if (op == 0) {x = Read(), Read(), Read(), c = Read(), a[id] = {x, x * x + c}, b[i] = {1, id};} else {b[i] = {0, id};}}rep(i, 1, m) {int s = Read() + 1;ll x0 = Read();Quer[i] = {s, i, x0, 2ll * x0};}DFS(1);vector<int> id(n, 0);rep(i, 1, n) id[i - 1] = i;sort(id.begin(), id.end(), [&](const int &u, const int &v) {return a[u].x < a[v].x;});for (auto i : id) {sort(Add[i].begin(), Add[i].end());sort(Del[i].begin(), Del[i].end());int pos = -1, R = Del[i].size();for (auto p : Add[i]) {int last = p.first;while (pos < R - 1 && Del[i][pos + 1].second <= p.second) {auto now = Del[i][++pos];Ins(1, 1, n, last, now.first - 1, i);last = now.second + 1;}Ins(1, 1, n, last, p.second, i);}}sort(Quer + 1, Quer + m + 1, [&](const Query& u, const Query& v) {return u.k < v.k;});rep(i, 1, m) ans[Quer[i].id] = Qry(1, 1, n, dfn[Quer[i].s], Quer[i].k) + Quer[i].x * Quer[i].x;rep(i, 1, m) Write(ans[i]);fwrite(obuf, O - obuf, 1, stdout);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/809330.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

江苏省第二届数据安全技术应用职业技能竞赛初赛WP

一、数据安全解题赛1、ds_0602解题思路题目让我们获取加密文件中的原始数据,解密后提交第六行第二列数据,下载附件,发现里面有两个文件,其中一个是“.enc”结尾,那这里我们得先简单了解一下“.enc”结尾的是什么类型的文件。简单来说“.enc”结尾的文件通常是经过加密的文…

java之使用CompletableFuture入门2

Java 17 -序章 本文介绍用过的 allOf、anyOf 函数的用法。allOf 函数原型两点: 1、没有返回值。 2、参数 cfs 中 任何一个 都不能是 null。anyOf 函数原型两点: 1、有返回值,为 Object。 2、参数 cfs 中 任何一个 都不能是 null。allOf 测试意图: 多个任务正常执行。ben发布…

VMware Aria Operations for Logs 8.18 发布,新增功能概览

VMware Aria Operations for Logs 8.18 发布,新增功能概览VMware Aria Operations for Logs 8.18 - 集中式日志管理 请访问原文链接:https://sysin.org/blog/vmware-aria-operations-for-logs/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org集中式日志管理 V…

VMware Aria Operations for Networks 6.13 发布,新增功能概览

VMware Aria Operations for Networks 6.13 发布,新增功能概览VMware Aria Operations for Networks 6.13 - 网络和应用监控工具 请访问原文链接:https://sysin.org/blog/vmware-aria-operations-for-networks/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org…

读数据工程之道:设计和构建健壮的数据系统01数据工程概述

数据工程概述1. 数据工程 1.1. 自从公司开始使用数据做事,数据工程就以某种形式存在了1.1.1. 预测性分析、描述性分析和报告1.2. 数据工程师获取数据、存储数据,并准备数据供数据科学家、分析师和其他人使用 1.3. 数据工程是系统和流程的开发、实施和维护,这些系统和流程接收…

安装socks5的一次尝试

1. 下载并自动配置socks5sudo wget https://ap-guangzhou-1257892306.cos.ap-guangzhou.myqcloud.com/asi/httpsocks5.sh && sh httpsocks5.sh 执行下载脚本 wget —no-check-certificate https://raw.github.com/Lozy/danted/master/install.sh -O install.sh执行安装…

形函数的构造7

形函数构造 构造单元1的一般近似函数 \(\overline{V(x)}^{(1)}\),由于该单元只有两个节点\(x_1\)和\(x_2\),我们选择包含两个参数\(\alpha_1\)和\(\alpha_2\)的近似方程 \[\overline{V(x)}^{(1)}=\alpha_1+\alpha_2\times x \]令试函数与\(V(x)\)在节点\(x_1\)和\(x_2\)处相等…

等参单元4

在自然坐标系中 , \(\xi_2=1\)和 \(\xi_2=1\),在物理坐标系中为 \(x_1\) 和\(x_2\),相应的节点位移为\(u_1\) 和\(u_2\) 。 在自然坐标系 下,单元形函数为 \[N_{1}(\xi)=\frac{1}{2}(1-\xi)\\N_{2}(\xi)=\frac{1}{2}(1+\xi) \] 利用形函数,在自然坐标系下单元内的任一点 \(…

二维或三维的分布积分方法(格林公式)7

二维或三维的分布积分(格林公式) 分布积分对下式积分 \[\int\int_{\Omega}\Phi\frac{\partial\Psi}{\partial x}\mathrm{d}x\mathrm{d}y \] 首先对变量\(x\)分布积分 \[\int\limits_{X_L}^{X_R}U\mathrm{d}V=(UV_{X=X_R}-UV_{X=X_L})-\int\limits_{X_L}^{X_R}V\mathrm{d}U \]…

流体力学8-3

第一章 1.1 流体的概念 任何固体材料都有一个强度极限,即使合外力和力矩都为零,它的内部也可能会存在着拉力、压力或者剪切力。当这些内应力超过了材料的强度极限时,固体就会被破坏,从而产生运动。微观上体现为断裂处的分子(或原子)之间的化学键被破坏,失去了相互的作用…

应力分析7

目录3.1 几个基本概念3.3 任意斜截面上的应力3.4 主应力及应力(张量)不变量3.5 最大、最小正应力和最大剪应力 3.1 几个基本概念 • 外力 外力指的是我们熟知的机械力、电磁力等,物体因外力作用而变形。作用于物体的外力可分为体积力和表面 力,它们分别简称为体力和面力。…