This commit is contained in:
Zengtudor 2024-11-11 17:58:48 +08:00
parent b9b726c22f
commit dfdf354730
4 changed files with 84 additions and 1 deletions

Binary file not shown.

3
src/20241111/U101804.cpp Normal file
View File

@ -0,0 +1,3 @@
int main(){
}

71
src/20241111/U101804.md Normal file
View File

@ -0,0 +1,71 @@
这个问题涉及树的遍历和动态更新,需要我们计算路径得分的期望。由于每个修改都可能影响某条路径的期望得分,因此要高效地处理初始计算和后续更新。
### 解题思路:
1. **树的构建**
- 给定父节点数组,可以构建一棵以 $1$ 为根的有根树。用一个邻接表来存储子节点信息。
2. **初始状态下期望得分的计算**
- 使用深度优先搜索DFS计算期望得分。
- 从根节点出发,递归计算每个节点的得分期望,遵循给定的转移概率 $\frac{w_v}{\text{sum}_u}$。
- 对于一个节点 $u$,其期望得分 $E(u)$ 可以递归计算为:
\[
E(u) = a_u + \sum_{v \in \text{children of } u} \frac{w_v}{\text{sum}_u} \cdot E(v)
\]
3. **处理修改操作**
- 每次修改某个节点 $u$ 的 $w$ 或 $a$ 值后,需要更新与 $u$ 相关的所有路径的期望。
- 直接重新运行DFS在大规模数据$n, q \leq 100,000$)中代价过高,因此需使用某种增量更新方法。
- 可以使用**树链剖分**或**树状数组**来高效更新受影响的子树或路径。
4. **取模运算**
- 由于结果需要对 $998244353$ 取模,所有的运算,包括除法,都需要用模逆元处理。
- 对于 $p$ 是素数,$x$ 的逆元为 $x^{p-2} \bmod p$,使用快速幂算法计算。
### 具体步骤:
1. **预处理**
- 构建树并计算初始期望得分 $E(1)$。
- 用 DFS 遍历每个节点计算期望得分的初始值。
2. **更新操作**
- 修改 $u$ 的 $w$ 或 $a$ 值后,调整 $u$ 的父节点期望,并递归更新到根节点。
- 使用自底向上的路径更新机制,通过父节点的影响逐步更新。
3. **实现细节**
- 采用链式前向星或邻接表存储树结构。
- 使用分块思想或其他树状数据结构如**树链剖分**,以便快速定位并更新路径。
### 复杂度分析:
- **时间复杂度**:初始期望计算为 $O(n)$,每次修改和更新平均为 $O(\log n)$ 或更低,具体取决于使用的数据结构。
- **空间复杂度**$O(n)$ 用于存储树结构和权值数组。
### 实现关键点:
- **DFS 计算期望**
```cpp
void dfs(int u) {
E[u] = a[u];
for (int v : children[u]) {
dfs(v);
E[u] += (w[v] * E[v]) / sum_u; // 注意使用模逆元
}
}
```
- **更新期望**
```cpp
void update(int u, int new_w, int new_a) {
w[u] = new_w;
a[u] = new_a;
// 使用树状数组或其他机制更新相关路径的期望
}
```
### 注意事项:
- 确保处理浮点除法时使用模运算。
- 根据问题的规模,考虑使用平衡树或线段树来优化更新操作。
这个解法需要巧妙地结合树结构和概率论来计算路径上的期望,并进行高效的更新。

View File

@ -2,6 +2,7 @@
#include <cstdint>
#include <functional>
#include <iostream>
#include <istream>
#include <limits>
#include <ostream>
#include <queue>
@ -10,19 +11,27 @@
using ll = int64_t;
const ll max_m = 1e3 + 5, max_n = max_m, inf = std::numeric_limits<ll>::max();
const ll max_m = 1e4 + 5, max_n = max_m, inf = std::numeric_limits<ll>::max();
ll n, m, s, dists[max_n];
struct Edge{
ll u,v,x,y,t;
}edges[max_m];
int main(){
std::iostream::sync_with_stdio(false), std::cin.tie(nullptr), std::cout.tie(nullptr);
std::fill(dists, dists+max_n, inf);
std::cin>>n>>m>>s;
dists[s]=0;
for(ll i{1};i<=m;i++){
const auto swap_big_small = []<class T>(T &a, T &b)->void{
if(a>b){std::swap(a,b);}
};
std::cin>>edges[i].u>>edges[i].v>>edges[i].x>>edges[i].y>>edges[i].t;
swap_big_small(edges[i].u, edges[i].v);
swap_big_small(edges[i].x, edges[i].y);
}
std::priority_queue<std::pair<ll, ll>, std::vector<std::pair<ll, ll>>, std::greater<>> pq;