模拟赛总结(三)
2024.9.16
重新定义饮料为一大杯冰沙
胃:这把生死局(指抿一口就开始起反应...)
早上就不停反呕,下午整这一出真是笑嘻了
T1 不相邻集合
以为贪心假的,结果对了
就是对新加的数看看有没有左邻右舍被取过,没有就计入答案
T2 线段树
暴力
考虑到线段树开点方式,点编号之和肯定可以写成一次函数,具体的,设
然后有关系
代入表达式可得:
可以记忆化处理
然后正常跑查询,如果找到
byd mid没开ll耗掉不少时间,被#define int long long教育力
T4 园艺
听说数据很水最多枚举两个拐点可过..
正解鞋油+单队,感觉和之前掉馅饼的题很像
2024.9.22
菜死了
T1 自然数
下洗了,不会
先求出
接下来枚举左端点,每次移动都为删掉一个
然后上线段树做区间修改,区间最值,区间求和即可
T2 钱仓
手膜膜错辣
改过来后发现就是贪心,然后存在这样一个点:该点后面的点的货物不会运到该点前面
这个点满足是最大子段和的起点(意思就是有足够多的货补给后面),由此处破环成链贪心即可
T3 游戏
考场上拿无穷近似推了个贼像的式子,然而还是遗憾离场
T4 暴雨
正解大炮,???
2024.9.28
T1 一般图最小匹配
贪心可以有
damn
整洁大炮
先对
定义
则
使用滚动优化
T2 重定向
暴力枚举删除位+填数有一半分
考虑到字典序最小,使用贪心
设
-
如果minn_i < minnum,就要把
删掉往这里放 -
,则删掉 更优 ,如果 ,那么删掉 更优
可以用优先队列维护要填的数
T3 斯坦纳树
T4 直径
2024.10.2
障保龄而东之,回暴力于既倒
T2 肥胖
忘了可以从
为了成功,肯定想要把限制放大点
于是可以建最大生成树
然后考虑选择的边中最小的,设为
证明的话,考虑反复横跳吃的某一步肯定是吃了一棵子树的最后一个然后跳到另一个,此时经过
然后考虑答案,设
假设从以
注:由于一开始
T3 分摊
看到分数吓似了
实际上大概是这样:只有儿子全满了自己才开始存钱
设
然后打
考虑到增量的维护,由于每一层都要和
考虑一次跳跃,当上面的
那么就可以统一计算:二分
T4 修路
暴力有
暴力时发现交点在圆内当且仅当两个由端点形成的区间严格相交(不取等)
由此可以维护区间,打log可以使用线段树一类物质
T1 战争
口胡可得
2024.10.3
亲手杀死整洁
T2 寻宝
看到传送门单向直接ban掉并查集,事后发现可以在并查集上建单向边跑暴力,毕竟最多
T1 构造字符串
手玩出
正解就是相同的合并成块,然后
然后填数,块内有位置填了直接染掉即可,否则求
T3 序列
官方题解:
容易发现这是一个与斜率有关的题目,这种题目通常通过维护凸包,或者李超树维护
跨过的区间容易转化为:以 为右端点的最优+以 为左端点的最优
两个问题同理,以右端点()为例
设,
最优即
即,离线之后李超树维护直线即可
时间复杂度为,常数略大,空间复杂度为
往李超上套,就是把
T4 构树
gugugugugugu~
2024.10.4
人死了一白天晚上才缓过来
T1 玩游戏
贪心写假了
不能只看挪动一位下左右谁最优,可能当前并入一个相对较大的数但是可以再并一个很小的负数,所以要用前缀和分别把左右指针推到极小处,考虑到极小处不一定是端点,所以要反着从端点往极小处跑,同样用前缀和实现
T2 排列
T3 最短路
std太吊
将返回等价为建反边后的前往,然后用dijkstra分别推进两个支路,使用bitset助力维护
设
T4 矩形
矩形重叠想到扫描线,但不会写
2024.10.5
T1 送花
从左往右扫,贡献是
T2 星空
考虑转换坐标系
将原坐标系顺时针旋转
最小距离的话就分别按
T3 零一串
吊炸天
T4 Revive
线段树 +
2024.10.6
虚死了
不太想写东西,扔
T1b
T2 竞赛图
T3 糖果
T4 树
2024.10.7
题目标题说得对
T1莓良心
糖,以为
若干个区间相交的标志:
对于剩余未相交区间,在
每次更新
T3 团不过
正难则反
设
考虑求
既然要让异或和为
答案:
T2 尽梨了
枚举
-
: 有一些 的位置是 ,而矩阵中是 ,那么 对应位置就要放 -
: 同理, 只能放 -
: 此时 可以全部接住 , 可以随便选
考虑计算
注意到
如果不存在
二者相互独立
接下来考虑判定合法,考虑到
T4 七负我
特殊性质(菊花图)提示我们均分最优,实际上确实如此,证明可以看看,接着就是求最大团,可以使用
2024.10.8
简单考了一场以替换月考
T1 哈希结果空间小了 T2 Tarjan忘了 T3 贪心假了...
放个链接
2024.10.13
都想到一点但不多
T1 Hunter
其实很简单,想复杂了
只有其他猎人在
T2 Defence
一眼看出是最长连续
有坑:如
使用线段树合并,维护区间最大
T3 Connect
一眼最大生成树然后加回去一部分删的边,但是不好维护,因为可能加着加着就把儿子连起来成新路径了
后来想到给
使用状压,预处理出所有能往主链上挂的东西
然后
2024.10.14
byd被wx和hl双重问候
T1score and rank
思路比较接近std,想到用堆维护
解释:遇到负数就把他摆平,如果当前总和小于负数绝对值就直接将总和置为
T2 HZOI大作战
一眼倍增,不会维护...
解释:等价于重定义
T4 gtm和joke的星球
斯坦纳树板子,原理就是最终连通图必定是个树,使用状压进行两种操作:
1.合并:将有相同根的点集合并
2.换根:使用最短路更新点集的根使得边权和尽可能的小
对每个点先进行第一步,再对整个点集进行第二步
T3 Delov的旅行
只能意会..
2024.10.15
T1 限速(speed)
比较简单,建出最小生成树,如果树内最大边大于
T2 酒鬼 (drunkard)
把题审成部分分了,就只有部分分了(
使用set维护,因为线索相互影响,要按时间排序再搞
发现
但是还有一些线索会影响
其他线索的维护就比较简单:插入
后一条在判断时间上距离
再加上特判有没有前驱后继等乱七八糟的细节 以及调试,长度来到惊人的
T3 距离(distance)
乱搞
枚举点对,形成的贡献作用范围是
T4 团队选拔(selection)
2024.8.6 T4原题 战绩可查
2024.10.16
糖死了把文件工工整整放到
T1 第一题
睡了导致什么也没有写...
只要占领全部叶子,其他点就占完了,所以考虑怎么占完叶子
占领一个叶子节点要么从其他叶子转移,要么从根新派一个兵,对于前者事先按照深度排序,然后对于每个叶子决策两种方式计算
T2 第二题
二分答案,然后遍历所有点把差抹平到二分值以下,计算所需代价是否超过
考虑换一种方式:建图遍历,用类似
T3 第三题
数位
利用
考虑怎么判断卡不卡界限(由于对区间所有数排序所以初始状态下一定卡)
对于上界,当前在第
更多细节看代码
T4 第四题
大炮
2024.10.17
T1 传送 (teleport)
分别按照
T2 排列 (permutation)
考虑到最多只有
设
枚举最后一位放什么即可,如果上一位和这一位都是关键数则需要检查
T3 战场模拟器 (simulator)
大数据结构模拟题
对于护甲和死亡,分类讨论,如果当前区间有护甲/死亡人数就要递归到叶子,否则就是普通的区间修改,需要写两个函数,
T4 点亮 (light)
2024.10.19
暴力不挂好心情~
由于是后期补的,没太多时间写,所以扔篇大题解
T1 排列最小生成树
暴力
T2 卡牌游戏 (cardgame)
把
T3 比特跳跃 (jump)
就按照题解说的模拟就行了
T4 区间 (interval)
咕咕咕
2024.10.20
T1 Reverse
发现每次交换
T2 Silhouette
先对
T3 Seat
一个结论是,对于任意一个人,他坐下时离最近的人的距离是一定的,那么可以将所有人按照坐下时的距离分成若干层。对于距离为
考虑到偶区间存在两个备选位置,两个位置是等价的,因此钦定一个人坐在某个位置,得到一系列答案,再对称推出选另一个位置的答案即可
T4 万猪拱塔
咕咕咕
2024.10.21
看到大家都不会做就放心了
T2没判误解挂了
T1 岛屿
怎么说呢。。。
T2 最短路
考虑建立最短路树,以1为根节点。
如果把点
这样需要枚举非树边,为了减少时间复杂度,不妨考虑一条非树边的贡献
如图,对于非树边但这题暴力跳父亲也能过
T3 列表
第一个性质可以导出第二个性质
定义双指针
根据性质2的等价转换(区间内至少有
这里有个巧妙的转化:对于一个位置,枚举到它时的
那么每跳一次
T4 种植
对偶图的意思就是说新建一个图(此题中新图似乎还不是对偶图,那玩意儿是最小割用的,这里只是单纯沿用定义),新图的边与旧图的边恰好有一个交点,对应题目中的每条路径上恰好一株农作物
考虑怎么处理障碍物。对角线肯定是沿着空地延伸的,当遇到障碍时,需要跳到障碍旁边的空地以继续延伸,所以将障碍周围的三个格子合并入他自己,就是所谓的四联通块缩点,然后直接对缩的点和空地连边即可
求路径数用拓扑序就行了
2024.10.22
简单签到+暴力乱c
T1 冒泡排序
就是对
T2 染色
暴力完全写不出来
就是把整个区间分成若干个色段,分成
T4 山峦(mountain)
数据范围注定这题很暴力,搜索都有
考虑到一行填数方案最多
设
原始的方法是枚举相邻行
T3 图
标程
感受一下威压
#include <cstdio>
#include <map>
#include <iostream>
#include <algorithm>
#include <bitset>
#include <queue>
#include <stack>
#include <vector>
#include <random>
#include <cstring>
#include <ctime>
#include <cmath>
#include <assert.h>
#include <unordered_map>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/hash_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
#define LL long long
#define pp pair<LL, LL>
#define mp make_pair
#define ull unsigned long long
namespace IO {
const int sz = 1 << 22;
char a[sz + 5], b[sz + 5], *p1 = a, *p2 = a, *t = b, p[105];
inline char gc() {
// return p1==p2?(p2=(p1=a)+fread(a,1,sz,stdin),p1==p2?EOF:*p1++):*p1++;
return getchar();
}
template <class T>
void gi(T& x) {
x = 0;
int f = 1;
char c = gc();
if (c == '-')
f = -1;
for (; c < '0' || c > '9'; c = gc())
if (c == '-')
f = -1;
for (; c >= '0' && c <= '9'; c = gc()) x = x * 10 + (c - '0');
x = x * f;
}
inline void flush() { fwrite(b, 1, t - b, stdout), t = b; }
inline void pc(char x) {
*t++ = x;
if (t - b == sz)
flush();
}
template <class T>
void pi(T x, char c = '\n') {
if (x < 0)
pc('-'), x = -x;
if (x == 0)
pc('0');
int t = 0;
for (; x; x /= 10) p[++t] = x % 10 + '0';
for (; t; --t) pc(p[t]);
pc(c);
}
struct F {
~F() { flush(); }
} f;
} // namespace IO
using IO::gi;
using IO::pc;
using IO::pi;
const int mod = 1e9 + 7;
inline int add(int x, int y) { return x + y >= mod ? x + y - mod : x + y; }
inline int dec(int x, int y) { return x - y < 0 ? x - y + mod : x - y; }
inline int mul(int x, int y) { return 1ll * x * y % mod; }
inline int qkpow(int a, int b) {
if (b < 0)
return 0;
int ans = 1, base = a % mod;
while (b) {
if (b & 1)
ans = 1ll * ans * base % mod;
base = 1ll * base * base % mod;
b >>= 1;
}
return ans;
}
int fac[1000005], inv[1000005], Invn[600005];
inline int binom(int n, int m) {
if (n < m || m < 0)
return 0;
return 1ll * fac[n] * inv[m] % mod * inv[n - m] % mod;
}
void init_C(int n) {
fac[0] = 1;
for (int i = 1; i <= n; i++) fac[i] = 1ll * fac[i - 1] * i % mod;
inv[0] = 1;
inv[n] = qkpow(fac[n], mod - 2);
for (int i = n - 1; i >= 1; i--) inv[i] = 1ll * inv[i + 1] * (i + 1) % mod;
Invn[0] = Invn[1] = 1;
for (int i = 1; i <= 200000; i++) Invn[i] = (LL)(mod - mod / i) * Invn[mod % i] % mod;
}
const LL INF = 1e18;
struct node3 {
pp mi1, mi2;
inline void init() { mi1 = mi2 = pp(INF, 0); }
} g1[100005], g2[100005], wg1[100005], wg2[100005];
inline void Add(node3& w1, pp w2) {
if (!w2.second)
return;
if (w1.mi1.second == w2.second)
w1.mi1.first = min(w1.mi1.first, w2.first);
else if (w1.mi2.second == w2.second) {
w1.mi2.first = min(w1.mi2.first, w2.first);
if (w1.mi1.first > w1.mi2.first)
swap(w1.mi1, w1.mi2);
} else {
if (w2.first < w1.mi1.first)
w1.mi2 = w1.mi1, w1.mi1 = w2;
else if (w2.first < w1.mi2.first)
w1.mi2 = w2;
}
}
int Log[100005];
struct ST_min {
node3 f[100005][21];
inline node3 query(int l, int r) {
node3 res;
res.init();
if (l > r)
return res;
int k = Log[r - l + 1];
res = f[r - (1 << k) + 1][k];
Add(res, f[l][k].mi1);
Add(res, f[l][k].mi2);
return res;
}
inline void init(int N) {
for (int j = 1; (1 << j) <= N; j++)
for (int i = 1; i + (1 << j) - 1 <= N; i++) {
f[i][j] = f[i + (1 << (j - 1))][j - 1];
Add(f[i][j], f[i][j - 1].mi1);
Add(f[i][j], f[i][j - 1].mi2);
}
}
} T1[2], T2[2];
int son1[100005], son2[100005], dep11[100005], dep22[100005], seg1[100005], seg2[100005], rev11[100005],
rev22[100005];
int top1[100005], top2[100005];
int n, fa[200005], id1[100005], id2[100005], cnt1, cnt2, dfn1[100005], dfn2[100005];
int rev1[100005], rev2[100005], f2[100005][21], sz1[100005], sz2[100005], f1[100005][21];
int st1[100005][21], st2[100005][21];
LL jp1[100005][21], jp2[100005][21];
LL dep1[100005], dep2[100005];
pp mn[200005];
struct node {
int to, w;
};
vector<node> G1[100005], G2[100005];
inline int findSet(int u) { return fa[u] == u ? u : fa[u] = findSet(fa[u]); }
inline int Min1(int u, int v) { return dfn1[u] < dfn1[v] ? u : v; }
inline int Min2(int u, int v) { return dfn2[u] < dfn2[v] ? u : v; }
inline int LCA1(int u, int v) {
if (u == v)
return u;
if ((u = dfn1[u]) > (v = dfn1[v]))
swap(u, v);
int k = Log[v - u++];
return Min1(f1[u][k], f1[v - (1 << k) + 1][k]);
}
inline int LCA2(int u, int v) {
if (u == v)
return u;
if ((u = dfn2[u]) > (v = dfn2[v]))
swap(u, v);
int k = Log[v - u++];
return Min2(f2[u][k], f2[v - (1 << k) + 1][k]);
}
inline LL getdis(int op, int u, int v) {
if (op == 1)
return dep1[u] + dep1[v] - 2 * dep1[LCA1(u, v)];
else
return dep2[u] + dep2[v] - 2 * dep2[LCA2(u, v)];
}
inline void dfs1(int u, int ff) {
dep11[u] = dep11[ff] + 1;
f1[dfn1[u] = ++cnt1][0] = ff;
rev1[cnt1] = u;
sz1[u] = 1;
for (int i = 1; i <= 20; i++)
st1[u][i] = st1[st1[u][i - 1]][i - 1], jp1[u][i] = jp1[u][i - 1] + jp1[st1[u][i - 1]][i - 1];
for (auto to : G1[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
dep1[v] = dep1[u] + w;
st1[v][0] = u, jp1[v][0] = w;
dfs1(v, u);
sz1[u] += sz1[v];
if (sz1[v] > sz1[son1[u]])
son1[u] = v;
}
}
inline void dfs11(int u, int ff) {
if (son1[u]) {
seg1[son1[u]] = ++seg1[0];
top1[son1[u]] = top1[u];
rev11[seg1[0]] = son1[u];
dfs11(son1[u], u);
}
for (auto to : G1[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
if (!top1[v]) {
seg1[v] = ++seg1[0];
top1[v] = v;
rev11[seg1[0]] = v;
dfs11(v, u);
}
}
}
inline void dfs2(int u, int ff) {
dep22[u] = dep22[ff] + 1;
f2[dfn2[u] = ++cnt2][0] = ff;
rev2[cnt2] = u;
sz2[u] = 1;
for (int i = 1; i <= 20; i++)
st2[u][i] = st2[st2[u][i - 1]][i - 1], jp2[u][i] = jp2[u][i - 1] + jp2[st2[u][i - 1]][i - 1];
for (auto to : G2[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
dep2[v] = dep2[u] + w;
st2[v][0] = u, jp2[v][0] = w;
dfs2(v, u);
sz2[u] += sz2[v];
if (sz2[v] > sz2[son2[u]])
son2[u] = v;
}
}
inline void dfs22(int u, int ff) {
if (son2[u]) {
seg2[son2[u]] = ++seg2[0];
top2[son2[u]] = top2[u];
rev22[seg2[0]] = son2[u];
dfs22(son2[u], u);
}
for (auto to : G2[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
if (!top2[v]) {
seg2[v] = ++seg2[0];
top2[v] = v;
rev22[seg2[0]] = v;
dfs22(v, u);
}
}
}
struct node2 {
pp u, v;
} t[400005], po1[100005], po2[100005];
LL tag[400005];
#define ls(u) u << 1
#define rs(u) u << 1 | 1
inline node2 merge(int op, node2 A, node2 B) {
node2 tmp;
LL res = -1;
LL d1 =
(A.u.first == A.v.first ? A.u.second : A.u.second + A.v.second) + getdis(op, A.u.first, A.v.first);
LL d2 =
(B.u.first == B.v.first ? B.u.second : B.u.second + B.v.second) + getdis(op, B.u.first, B.v.first);
LL d3 =
(A.u.first == B.v.first ? A.u.second : A.u.second + B.v.second) + getdis(op, A.u.first, B.v.first);
LL d4 =
(B.u.first == A.v.first ? B.u.second : B.u.second + A.v.second) + getdis(op, B.u.first, A.v.first);
LL d5 =
(A.u.first == B.u.first ? A.u.second : A.u.second + B.u.second) + getdis(op, A.u.first, B.u.first);
LL d6 =
(A.v.first == B.v.first ? A.v.second : A.v.second + B.v.second) + getdis(op, A.v.first, B.v.first);
res = max(d1, d2), res = max(res, max(d3, d4)), res = max(res, max(d5, d6));
if (d1 == res)
tmp = node2{ A.u, A.v };
if (d2 == res)
tmp = node2{ B.u, B.v };
if (d3 == res)
tmp = node2{ A.u, B.v };
if (d4 == res)
tmp = node2{ B.u, A.v };
if (d5 == res)
tmp = node2{ A.u, B.u };
if (d6 == res)
tmp = node2{ A.v, B.v };
return tmp;
}
inline void push_down(int u) {
if (tag[u]) {
tag[ls(u)] += tag[u];
tag[rs(u)] += tag[u];
t[ls(u)].u.second += tag[u];
t[ls(u)].v.second += tag[u];
t[rs(u)].u.second += tag[u];
t[rs(u)].v.second += tag[u];
tag[u] = 0;
}
}
inline void updata(int op, int p, int l, int r, int L, int R, int w) {
if (L > R)
return;
if (L <= l && r <= R) {
tag[p] += w;
t[p].u.second += w;
t[p].v.second += w;
return;
}
push_down(p);
int mid = (l + r) >> 1;
if (L <= mid)
updata(op, ls(p), l, mid, L, R, w);
if (mid + 1 <= R)
updata(op, rs(p), mid + 1, r, L, R, w);
t[p] = merge(op, t[ls(p)], t[rs(p)]);
}
inline void build(int op, int p, int l, int r) {
tag[p] = 0;
if (l == r) {
if (op == 2)
t[p].u = t[p].v = pp(rev1[l], dep1[rev1[l]]);
else
t[p].u = t[p].v = pp(rev2[l], dep2[rev2[l]]);
return;
}
int mid = (l + r) >> 1;
build(op, ls(p), l, mid);
build(op, rs(p), mid + 1, r);
t[p] = merge(op, t[ls(p)], t[rs(p)]);
}
inline void redfs1(int u, int ff) {
po1[u] = t[1];
for (auto to : G1[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
updata(2, 1, 1, n, dfn1[v], dfn1[v] + sz1[v] - 1, -w);
updata(2, 1, 1, n, 1, dfn1[v] - 1, w);
updata(2, 1, 1, n, dfn1[v] + sz1[v], n, w);
redfs1(v, u);
updata(2, 1, 1, n, dfn1[v], dfn1[v] + sz1[v] - 1, w);
updata(2, 1, 1, n, 1, dfn1[v] - 1, -w);
updata(2, 1, 1, n, dfn1[v] + sz1[v], n, -w);
}
}
inline void redfs2(int u, int ff) {
po2[u] = t[1];
for (auto to : G2[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
updata(1, 1, 1, n, dfn2[v], dfn2[v] + sz2[v] - 1, -w);
updata(1, 1, 1, n, 1, dfn2[v] - 1, w);
updata(1, 1, 1, n, dfn2[v] + sz2[v], n, w);
redfs2(v, u);
updata(1, 1, 1, n, dfn2[v], dfn2[v] + sz2[v] - 1, w);
updata(1, 1, 1, n, 1, dfn2[v] - 1, -w);
updata(1, 1, 1, n, dfn2[v] + sz2[v], n, -w);
}
}
inline void dfss1(int u, int ff) {
g1[u].init();
wg1[u].init();
Add(g1[u], pp(0, id1[u]));
for (auto to : G1[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
dfss1(v, u);
Add(g1[u], pp(g1[v].mi1.first + w, g1[v].mi1.second));
Add(g1[u], pp(g1[v].mi2.first + w, g1[v].mi2.second));
}
}
inline void redfss1(int u, int ff) {
node3 pre;
pre.init();
Add(wg1[u], pp(0, id1[u]));
for (auto to : G1[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
Add(wg1[v], pp(wg1[u].mi1.first + w, wg1[u].mi1.second));
Add(wg1[v], pp(wg1[u].mi2.first + w, wg1[u].mi2.second));
Add(wg1[v], pp(pre.mi1.first + w, pre.mi1.second));
Add(wg1[v], pp(pre.mi2.first + w, pre.mi2.second));
Add(pre, pp(g1[v].mi1.first + w, g1[v].mi1.second));
Add(pre, pp(g1[v].mi2.first + w, g1[v].mi2.second));
}
reverse(G1[u].begin(), G1[u].end());
pre.init();
for (auto to : G1[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
Add(wg1[v], pp(pre.mi1.first + w, pre.mi1.second));
Add(wg1[v], pp(pre.mi2.first + w, pre.mi2.second));
Add(pre, pp(g1[v].mi1.first + w, g1[v].mi1.second));
Add(pre, pp(g1[v].mi2.first + w, g1[v].mi2.second));
}
reverse(G1[u].begin(), G1[u].end());
for (auto to : G1[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
redfss1(v, u);
}
}
inline void dfss2(int u, int ff) {
g2[u].init();
wg2[u].init();
Add(g2[u], pp(0, id2[u]));
for (auto to : G2[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
dfss2(v, u);
Add(g2[u], pp(g2[v].mi1.first + w, g2[v].mi1.second));
Add(g2[u], pp(g2[v].mi2.first + w, g2[v].mi2.second));
}
}
inline void redfss2(int u, int ff) {
node3 pre;
pre.init();
Add(wg2[u], pp(0, id2[u]));
for (auto to : G2[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
Add(wg2[v], pp(wg2[u].mi1.first + w, wg2[u].mi1.second));
Add(wg2[v], pp(wg2[u].mi2.first + w, wg2[u].mi2.second));
Add(wg2[v], pp(pre.mi1.first + w, pre.mi1.second));
Add(wg2[v], pp(pre.mi2.first + w, pre.mi2.second));
Add(pre, pp(g2[v].mi1.first + w, g2[v].mi1.second));
Add(pre, pp(g2[v].mi2.first + w, g2[v].mi2.second));
}
reverse(G2[u].begin(), G2[u].end());
pre.init();
for (auto to : G2[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
Add(wg2[v], pp(pre.mi1.first + w, pre.mi1.second));
Add(wg2[v], pp(pre.mi2.first + w, pre.mi2.second));
Add(pre, pp(g2[v].mi1.first + w, g2[v].mi1.second));
Add(pre, pp(g2[v].mi2.first + w, g2[v].mi2.second));
}
reverse(G2[u].begin(), G2[u].end());
for (auto to : G2[u]) {
int v = to.to, w = to.w;
if (v == ff)
continue;
redfss2(v, u);
}
}
inline node3 query22(int op, int u, int v, LL ex) {
int fu = top2[u], fv = top2[v];
node3 res;
res.init();
while (fu != fv) {
if (dep22[fu] >= dep22[fv]) {
node3 tmp = T2[op].query(seg2[fu], seg2[u]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
u = st2[fu][0];
} else {
node3 tmp = T2[op].query(seg2[fv], seg2[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
v = st2[fv][0];
}
fu = top2[u], fv = top2[v];
}
if (dep22[u] > dep22[v])
swap(u, v);
node3 tmp = T2[op].query(seg2[u], seg2[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
return node3{ pp(res.mi1.first + ex, res.mi1.second), pp(res.mi2.first + ex, res.mi2.second) };
}
inline pp query2(int u, int v, LL w1, LL w2, int c) { //锟斤拷色锟斤拷锟斤拷锟斤拷 c
int lca = LCA2(u, v);
// if(lca!=1)cerr<<lca<<" "<<"FUCK"<<endl;
int to = u;
LL sum = w1, tot = getdis(2, u, v) + w1 + w2;
node3 res, tmp;
res.init();
LL ex = max(getdis(2, u, lca) + w1, getdis(2, v, lca) + w2);
Add(res, pp(wg2[lca].mi1.first + ex, wg2[lca].mi1.second));
Add(res, pp(wg2[lca].mi2.first + ex, wg2[lca].mi2.second));
if (w1 >= tot - w1) {
node3 tmp;
tmp = query22(1, u, lca, w1 + dep2[u]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
for (int i = 20; i >= 0; i--) {
if (sum + jp2[to][i] <= tot - sum - jp2[to][i]) {
sum += jp2[to][i];
to = st2[to][i];
}
}
node3 tmp;
if (dep22[to] <= dep22[lca]) { //全锟斤拷锟斤拷 v 锟斤拷
tmp = query22(0, u, lca, w2 + dep2[v] - 2 * dep2[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
tmp = query22(0, u, to, w2 + dep2[v] - 2 * dep2[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
tmp = query22(1, st2[to][0], lca, w1 + dep2[u]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
}
}
to = v;
sum = w2;
if (w2 >= tot - w2) {
tmp = query22(1, v, lca, w2 + dep2[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
for (int i = 20; i >= 0; i--) {
if (sum + jp2[to][i] <= tot - sum - jp2[to][i]) {
sum += jp2[to][i];
to = st2[to][i];
}
}
if (dep22[to] <= dep22[lca]) { //全锟斤拷锟斤拷 u 锟斤拷
tmp = query22(0, v, lca, w1 + dep2[u] - 2 * dep2[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
tmp = query22(0, v, to, w1 + dep2[u] - 2 * dep2[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
tmp = query22(1, st2[to][0], lca, w2 + dep2[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
}
}
if (res.mi1.second == c)
return res.mi2;
return res.mi1;
}
inline node3 query11(int op, int u, int v, LL ex) {
int fu = top1[u], fv = top1[v];
node3 res;
res.init();
while (fu != fv) {
if (dep11[fu] >= dep11[fv]) {
node3 tmp = T1[op].query(seg1[fu], seg1[u]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
u = st1[fu][0];
} else {
node3 tmp = T1[op].query(seg1[fv], seg1[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
v = st1[fv][0];
}
fu = top1[u], fv = top1[v];
}
if (dep11[u] > dep11[v])
swap(u, v);
node3 tmp = T1[op].query(seg1[u], seg1[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
return node3{ pp(res.mi1.first + ex, res.mi1.second), pp(res.mi2.first + ex, res.mi2.second) };
}
inline pp query1(int u, int v, LL w1, LL w2, int c) { //锟斤拷色锟斤拷锟斤拷锟斤拷 c
int lca = LCA1(u, v);
// if(lca!=1)cerr<<lca<<" "<<"FUCK"<<endl;
int to = u;
LL sum = w1, tot = getdis(1, u, v) + w1 + w2;
node3 res, tmp;
res.init();
LL ex = max(getdis(1, u, lca) + w1, getdis(1, v, lca) + w2);
Add(res, pp(wg1[lca].mi1.first + ex, wg1[lca].mi1.second));
Add(res, pp(wg1[lca].mi2.first + ex, wg1[lca].mi2.second));
if (w1 >= tot - w1) {
tmp = query11(1, u, lca, w1 + dep1[u]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
for (int i = 20; i >= 0; i--) {
if (sum + jp1[to][i] <= tot - sum - jp1[to][i]) {
sum += jp1[to][i];
to = st1[to][i];
}
}
node3 tmp;
if (dep11[to] <= dep11[lca]) { //全锟斤拷锟斤拷 v 锟斤拷
tmp = query11(0, u, lca, w2 + dep1[v] - 2 * dep1[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
tmp = query11(0, u, to, w2 + dep1[v] - 2 * dep1[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
tmp = query11(1, st1[to][0], lca, w1 + dep1[u]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
}
}
to = v;
sum = w2;
if (w2 >= tot - w2) {
node3 tmp;
tmp = query11(1, v, lca, w2 + dep1[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
for (int i = 20; i >= 0; i--) {
if (sum + jp1[to][i] <= tot - sum - jp1[to][i]) {
sum += jp1[to][i];
to = st1[to][i];
}
}
if (dep11[to] <= dep11[lca]) { //全锟斤拷锟斤拷 u 锟斤拷
tmp = query11(0, v, lca, w1 + dep1[u] - 2 * dep1[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
} else {
tmp = query11(0, v, to, w1 + dep1[u] - 2 * dep1[lca]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
tmp = query11(1, st1[to][0], lca, w2 + dep1[v]);
Add(res, tmp.mi1), Add(res, tmp.mi2);
}
}
if (res.mi1.second == c)
return res.mi2;
return res.mi1;
}
inline void solve() {
for (int i = 2; i <= 100000; i++) Log[i] = Log[i >> 1] + 1;
gi(n);
for (int i = 1; i < n; i++) {
int u, v, w;
gi(u), gi(v), gi(w);
G1[u].push_back(node{ v, w });
G1[v].push_back(node{ u, w });
}
for (int i = 1; i < n; i++) {
int u, v, w;
gi(u), gi(v), gi(w);
G2[u].push_back(node{ v, w });
G2[v].push_back(node{ u, w });
}
seg1[0] = seg1[1] = top1[1] = rev11[1] = 1;
seg2[0] = seg2[1] = top2[1] = rev22[1] = 1;
dfs1(1, 0), dfs2(1, 0), dfs11(1, 0), dfs22(1, 0);
for (int j = 1; (1 << j) <= cnt1; j++)
for (int i = 1; i + (1 << j) - 1 <= cnt1; i++)
f1[i][j] = Min1(f1[i][j - 1], f1[i + (1 << (j - 1))][j - 1]);
for (int j = 1; (1 << j) <= cnt2; j++)
for (int i = 1; i + (1 << j) - 1 <= cnt2; i++)
f2[i][j] = Min2(f2[i][j - 1], f2[i + (1 << (j - 1))][j - 1]);
build(2, 1, 1, n);
redfs1(1, 0);
build(1, 1, 1, n);
redfs2(1, 0);
for (int i = 1; i <= 2 * n; i++) fa[i] = i;
int cnt = 2 * n;
LL ans = 0;
while (cnt > 1) {
for (int i = 1; i <= n; i++) id1[i] = findSet(i), mn[i] = pp(INF, 0);
for (int i = 1; i <= n; i++) id2[i] = findSet(i + n), mn[i + n] = pp(INF, 0);
dfss1(1, 0), dfss2(1, 0);
redfss1(1, 0), redfss2(1, 0);
for (int i = 1; i <= n; i++) {
int u = rev11[i], v = rev22[i];
T1[0].f[i][0].mi1 = pp(g1[u].mi1.first + dep1[u], g1[u].mi1.second);
T1[0].f[i][0].mi2 = pp(g1[u].mi2.first + dep1[u], g1[u].mi2.second);
T1[1].f[i][0].mi1 = pp(g1[u].mi1.first - dep1[u], g1[u].mi1.second);
T1[1].f[i][0].mi2 = pp(g1[u].mi2.first - dep1[u], g1[u].mi2.second);
T2[0].f[i][0].mi1 = pp(g2[v].mi1.first + dep2[v], g2[v].mi1.second);
T2[0].f[i][0].mi2 = pp(g2[v].mi2.first + dep2[v], g2[v].mi2.second);
T2[1].f[i][0].mi1 = pp(g2[v].mi1.first - dep2[v], g2[v].mi1.second);
T2[1].f[i][0].mi2 = pp(g2[v].mi2.first - dep2[v], g2[v].mi2.second);
}
T1[0].init(n), T2[0].init(n), T1[1].init(n), T2[1].init(n);
for (int i = 1; i <= n; i++) {
int u = po1[i].u.first, v = po1[i].v.first;
LL w1 = po1[i].u.second, w2 = po1[i].v.second;
mn[id1[i]] = min(mn[id1[i]], query2(u, v, w1, w2, id1[i]));
}
for (int i = 1; i <= n; i++) {
int u = po2[i].u.first, v = po2[i].v.first;
LL w1 = po2[i].u.second, w2 = po2[i].v.second;
mn[id2[i]] = min(mn[id2[i]], query1(u, v, w1, w2, id2[i]));
}
for (int i = 1; i <= 2 * n; i++) {
if (mn[i].second) {
int u = i, v = mn[i].second;
u = findSet(u), v = findSet(v);
if (u != v) {
fa[v] = u;
ans += mn[i].first;
cnt--;
}
}
}
// cerr<<cnt<<endl;
}
pi(ans);
}
/*
要一锟斤拷锟斤拷锟斤拷
*/
signed main() {
freopen("graph.in", "r", stdin);
freopen("graph.out", "w", stdout);
srand(time(0));
solve();
return 0;
}
/*
*/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术