专栏文章
[COTS 2014] 城市建设 / GRAD
P11757题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @min8rj33
- 此快照首次捕获于
- 2025/12/01 22:25 3 个月前
- 此快照最后确认于
- 2025/12/01 22:25 3 个月前
LCA 原句:直接建三角形的树。我由这句话推出了与他很不一样的做法。
一句话题解:将三角形视为节点建图,图可以是一棵树,树上倍增。
本题解矩阵右乘。
本题的修改操作,每次相当于在图中添加一个三角形,且这个三角形与已有的某个三角形相连。从一个点到另一个点,相当于在三角形的边上不断移动,且每次都是从一个三角形切换到另一个三角形(由三角形不等式可得,在某个三角形上走两条边一定不优)。
既然如此,考虑图论建模,将三角形抽象成图上的点,两个三角形共用一条边时在图中将二者连接起来。每个三角形都记录一下他对应的三个城市是什么。三角形 A 到 B 的边权就是 的 矩阵,内容为 A 中某一点到 B 中某一点的最短路。由于两个三角形相邻,还有三角形不等式加持,随便求。
倘若我们知道了某城市到某三角形所对应三个城市的最短路程,再通过一条边就可以转移到下一个三角形。方法为:将三个距离记成一个 的矩阵,通过 矩阵乘法乘上该边边权。由于三角形不等式,不可能绕一大圈再过去。
在图上找路径不大可做,但我们发现其实可在树上做即可。如图:
三个三角形共用一条边,根本不需要连 条边, 条就够了。假如在图上连接了 和 、 和 ,一条从城市 到 的路径可以被视为 。同一个点之间的距离为 ,因此这样建图仍然可以得到正确答案。
转换成树就简单了。可以用倍增维护树上两点之间的路径矩阵之积。写起来有点屎。
CPP#include <mrpython/utility.hpp>
#include <bits/stdc++.h>
using namespace std;
istream& fin = cin;
ostream& fout = cout;
using ui = unsigned int;
using uli = unsigned long long int;
using li = long long int;
template <typename T, size_t N, size_t M> struct matrix {
T m[N][M];
template <typename F = std::plus<>>
friend matrix plus(matrix x, matrix const& y, F const& f = {}) {
for (size_t i = 0; i < N; ++i)
for (size_t j = 0; j < M; ++j)
x.m[i][j] = f(x.m[i][j], y.m[i][j]);
return x;
}
constexpr matrix& operator+=(matrix const& y) {
return plus(y);
}
constexpr friend matrix operator+(matrix x, matrix const& y) {
return x += y;
}
template <size_t L, typename F = std::plus<>, typename G = std::multiplies<>>
constexpr static matrix<T, N, L> multiplies(matrix<T, N, M> const& a,
matrix<T, M, L> const& b,
F const& f = {}, G const& g = {},
T const& init = 0) {
matrix<T, N, L> ans{};
for (size_t i = 0; i < N; ++i)
for (size_t j = 0; j < L; ++j) {
ans.m[i][j] = init;
for (size_t k = 0; k < M; ++k)
ans.m[i][j] = f(ans.m[i][j], g(a.m[i][k], b.m[k][j]));
}
return ans;
}
template <size_t L>
constexpr friend matrix<T, N, L> operator*(matrix<T, N, M> const& a,
matrix<T, M, L> const& b) {
return matrix<T, N, M>::multiplies<L>(a, b);
}
constexpr matrix& operator*=(matrix<T, M, M> const& x) {
return *this = *this * x;
}
};
using Mt = matrix<double, 3, 3>;
constexpr ui W = 20;
auto main(void) -> int {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
vector<complex<double>> ps;
{
ui x, y, z, w;
fin >> x >> y >> z >> w;
ps = {
{{(double)x, (double)y}, {(double)z, (double)w}}
};
}
vector<size_t> tids = {0, 0};
map<pair<size_t, size_t>, size_t> edges = {
{{0, 1}, 0}
};
vector<array<size_t, 3>> tps;
vector<size_t> deepth = {0};
vector<array<pair<size_t, Mt>, W>> jmp = {{}};
auto mgMt = []<typename T, size_t N, size_t M, size_t L>(
matrix<T, N, M> const& a, matrix<T, M, L> const& b) {
return matrix<T, N, M>::multiplies(a, b, mrpython::min(), plus(),
numeric_limits<double>::infinity());
};
size_t q;
fin >> q;
fout << fixed << setprecision(6);
while (q--) {
char op;
fin >> op;
if (op == 'd') {
complex<double> pv;
{
ui x, y;
fin >> x >> y;
pv = {(double)x, (double)y};
}
size_t px, py;
fin >> px >> py;
--px, --py;
if (px > py)
swap(px, py);
size_t pid = ps.size();
size_t tid = tps.size();
size_t fa = edges.at({px, py});
ps.emplace_back(pv);
tids.emplace_back(tid);
edges.insert({
{px, pid},
tid
});
edges.insert({
{py, pid},
tid
});
tps.push_back({px, py, pid});
if (tid != 0)
deepth.emplace_back(deepth[fa] + 1);
Mt mt;
for (size_t i = 0; i < 3; ++i)
for (size_t j = 0; j < 3; ++j) {
size_t pi = tps[tid][i], pj = tps[fa][j];
if (((tps[tid][i] == pid && tps[fa][j] != px && tps[fa][j] != py) ||
(tps[tid][j] == pid && tps[fa][i] != px && tps[fa][i] != py)) &&
!edges.contains({min(pi, pj), max(pi, pj)})) {
mt.m[i][j] = min(abs(ps[pi] - ps[px]) + abs(ps[px] - ps[pj]),
abs(ps[pi] - ps[py]) + abs(ps[py] - ps[pj]));
} else
mt.m[i][j] = abs(ps[pi] - ps[pj]);
}
if (tid != 0)
jmp.push_back({{{fa, mt}}});
for (size_t t = 1; t < W; ++t) {
size_t tm = jmp[tid][t - 1].first;
jmp[tid][t] = {jmp[tm][t - 1].first,
mgMt(jmp[tid][t - 1].second, jmp[tm][t - 1].second)};
}
} else if (op == 'u') {
size_t px, py;
fin >> px >> py;
--px, --py;
size_t tx = tids[px], ty = tids[py];
if (deepth[tx] < deepth[ty])
swap(px, py), swap(tx, ty);
matrix<double, 1, 3> mx, my;
for (size_t i = 0; i < 3; ++i) {
mx.m[0][i] = abs(ps[tps[tx][i]] - ps[px]);
my.m[0][i] = abs(ps[tps[ty][i]] - ps[py]);
}
for (ui t = W - 1; t < W; --t)
if (((deepth[tx] - deepth[ty]) >> t) & 1u) {
mx = mgMt(mx, jmp[tx][t].second);
tx = jmp[tx][t].first;
}
assert(deepth[tx] == deepth[ty]);
if (tx != ty) {
for (ui t = W - 1; t < W; --t)
if (jmp[tx][t].first != jmp[ty][t].first) {
mx = mgMt(mx, jmp[tx][t].second);
tx = jmp[tx][t].first;
my = mgMt(my, jmp[ty][t].second);
ty = jmp[ty][t].first;
}
mx = mgMt(mx, jmp[tx][0].second);
tx = jmp[tx][0].first;
my = mgMt(my, jmp[ty][0].second);
ty = jmp[ty][0].first;
}
assert(tx == ty);
double ans = numeric_limits<double>::infinity();
for (size_t i = 0; i < 3; ++i)
ans = min(ans, mx.m[0][i] + my.m[0][i]);
fout << ans << '\n';
}
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...