原代码:
//writer:Oier_szc
#include <bits/stdc++.h>
//#include <windows.h>
#define ED cerr<<endl;
#define TS cerr<<"I AK IOI"<<endl;
#define cr(x) cerr<<x<<endl;
#define cr2(x,y) cerr<<x<<" "<<y<<endl;
#define cr3(x,y,z) cerr<<x<<" "<<y<<" "<<z<<endl;
#define cr4(x,y,z,w) cerr<<x<<" "<<y<<" "<<z<<" "<<w<<endl;
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
//#define uint unsigned long long
using namespace std;
const int N=5e3+5,INF=1e18,mod=1e9+7;
int t,n,m,ans=0;
vector<int> e[N];
vector<pii> f[N];
int a[N];
vector<pii> merge(vector<pii> x,vector<pii> y) {
vector<pii> res;
int l=0,r=0,p=0,szx=x.size(),szy=y.size();
res.resize(szx+szy);
while(l<szx&&r<szy) {
if(x[l].fi>y[r].fi) res[p++]=x[l++];
else res[p++]=y[r++];
}
while(l<szx) res[p++]=x[l++];
while(r<szy) res[p++]=y[r++];
return res;
}
void dfs(int u) {
int now=0;
if(!e[u].size()) {
f[u].emplace_back(1,INF);
return;
}
for(auto to:e[u]) {
dfs(to),now+=a[to];
}
if(a[u]>now) {
for(auto to:e[u]) f[u]=merge(f[u],f[to]);
int ps=f[u].size()-1;
while(a[u]>now) {
int w=f[u][ps].fi,&v=f[u][ps].se;
if(v>a[u]-now) {
v-=a[u]-now;
ans+=(a[u]-now)*w;
now=a[u];
}
else {
ans+=v*w;
now+=v;
f[u].pop_back(),--ps;
}
}
}
else {
if(a[u]<now) f[u].emplace_back(0,now-a[u]);
for(auto to:e[u]) f[u]=merge(f[u],f[to]);
}
for(auto &it:f[u]) ++it.fi;
}
void sol() {
scanf("%lld",&n);
ans=0;
for(int i=1;i<=n;++i) {
scanf("%lld",&a[i]);
e[i].clear(),f[i].clear();
}
int u;
for(int i=2;i<=n;++i) {
scanf("%lld",&u);
e[u].emplace_back(i);
}
dfs(1);
printf("%lld\n",ans);
}
signed main()
{
scanf("%lld",&t);
while(t--) {
sol();
}
return 0;
}
这份代码卡在了第40个点MLE。第40个点之前的n大小都是几十的规模,而第40个点飙升至5000。
改了函数的合并:
//writer:Oier_szc
#include <bits/stdc++.h>
//#include <windows.h>
#define ED cerr<<endl;
#define TS cerr<<"I AK IOI"<<endl;
#define cr(x) cerr<<x<<endl;
#define cr2(x,y) cerr<<x<<" "<<y<<endl;
#define cr3(x,y,z) cerr<<x<<" "<<y<<" "<<z<<endl;
#define cr4(x,y,z,w) cerr<<x<<" "<<y<<" "<<z<<" "<<w<<endl;
#define pii pair<int,int>
#define fi first
#define se second
#define int long long
//#define uint unsigned long long
using namespace std;
const int N=5e3+5,INF=1e18,mod=1e9+7;
int t,n,m,ans=0;
vector<int> e[N];
vector<pii> f[N];
int a[N];
void merge(int u,int v) {
vector<pii> res;
int l=0,r=0,p=0,szx=f[u].size(),szy=f[v].size();
res.resize(szx+szy);
while(l<szx&&r<szy) {
if(f[u][l].fi>f[v][r].fi) res[p++]=f[u][l++];
else res[p++]=f[v][r++];
}
while(l<szx) res[p++]=f[u][l++];
while(r<szy) res[p++]=f[v][r++];
f[u].swap(res);
}
void dfs(int u) {
int now=0;
if(!e[u].size()) {
f[u].emplace_back(1,INF);
return;
}
for(auto to:e[u]) {
dfs(to),now+=a[to];
}
if(a[u]>now) {
for(auto to:e[u]) merge(u,to);
int ps=f[u].size()-1;
while(a[u]>now) {
int w=f[u][ps].fi,&v=f[u][ps].se;
if(v>a[u]-now) {
v-=a[u]-now;
ans+=(a[u]-now)*w;
now=a[u];
}
else {
ans+=v*w;
now+=v;
f[u].pop_back(),--ps;
}
}
}
else {
if(a[u]<now) f[u].emplace_back(0,now-a[u]);
for(auto to:e[u]) merge(u,to);
}
for(auto &it:f[u]) ++it.fi;
}
void sol() {
scanf("%lld",&n);
ans=0;
for(int i=1;i<=n;++i) {
scanf("%lld",&a[i]);
e[i].clear(),f[i].clear();
}
int u;
for(int i=2;i<=n;++i) {
scanf("%lld",&u);
e[u].emplace_back(i);
}
dfs(1);
printf("%lld\n",ans);
}
signed main()
{
//freopen("qwq.in","r",stdin);
scanf("%lld",&t);
while(t--) {
sol();
}
return 0;
}
AC了。
所以是什么原因。原代码得出的答案都是正确的,拿t神代码对拍过,可以保证不是代码思路的问题。