关于做上场CF E题遇到的MLE
  • 板块学术版
  • 楼主ShanQing
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/7/2 22:28
  • 上次更新2024/7/3 09:58:40
查看原帖
关于做上场CF E题遇到的MLE
368204
ShanQing楼主2024/7/2 22:28

原代码:

//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神代码对拍过,可以保证不是代码思路的问题。

2024/7/2 22:28
加载中...