一开始的代码是这样的。
#include<iostream>
#include<fstream>
#include<algorithm>
#include<vector>
#include<cstring>
#include<queue>
#define int long long
#define eb emplace_back
#define mp make_pair
//#define DEBUG
using namespace std;
const int P = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
using pii = pair<int, int>;
namespace azus{
int n;
vector<int> a;
vector<int> b;
vector<int> dep;
vector<vector<int> > edge;
vector<priority_queue<pii> > q;
int ans = 0;
int dfs(int u, int fa){
if(edge[u].size() == 1 && u != 1) b[u] = inf;
dep[u] = dep[fa] + 1;
for(int v : edge[u]){
if(v == fa) continue;
dfs(v, u);
while(!q[v].empty()){
auto x = q[v].top();
q[v].pop();
q[u].emplace(x);
}
}
if(b[u] > 0){
q[u].emplace(make_pair(-dep[u], u));
} else if(b[u] < 0){
while(b[u] < 0){
auto x = q[u].top();
q[u].pop();
int cost = (-x.first - dep[u]);
if(b[x.second] + b[u] > 0){
ans += cost * (-b[u]);
b[x.second] += b[u];
b[u] = 0;
q[u].emplace(x);
} else {
ans += cost * (b[x.second]);
b[u] += b[x.second];
b[x.second] = 0;
}
}
}
return 0;
}
int main(){
ans = 0;
cin >> n;
a.clear();
q.clear();
dep.clear();
edge.clear();
a.assign(n + 5, 0);
edge.assign(n + 5, vector<int> {});
dep.assign(n + 5, 0);
q.assign(n + 5, {});
for(int i = 1; i <= n; i ++)
cin >> a[i];
b = a;
for(int i = 2, p; i <= n; i ++){
cin >> p;
b[p] -= a[i];
edge[p].eb(i);
edge[i].eb(p);
}
for(int i = 1; i <= n; i ++)
b[i] = -b[i];
dfs(1, 0);
cout << ans << "\n";
return 0;
}
}
signed main(){
#ifndef DEBUG
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
#endif
int T = 1;
cin >> T;
while(T --)
azus::main();
return 0;
}
这份代码 MLE On Test40,后来我通过把 define int long long 删了过了。
但是我不是很理解,这里我开的所有 vector 中,edge 表示边,应该只会存 2(n−1) 个元素。而我在 vector 中开的优先队列,因为我在 dfs 过程中每次都会通过合并把其子节点优先队列的所有元素转移到当前节点的优先队列中并清空子节点的优先队列,所以理论在任意时刻只会同时存在 O(n) 级别的元素在所有优先队列中。
而这题 n≤5000,理论上空间占用应该非常小,即使全开 long long 都不会爆。因此我不理解为什么会 MLE,我觉得可能是 vector 的 assign 函数实现的问题。
求大佬解答!