关于MLE
查看原帖
关于MLE
205782
R浩轩泽Anmicius楼主2020/8/25 21:11

原题: P3353 在你窗外闪耀的星星

题目七夕屠狗系列

这道题显然用线段树,但在最后枚举答案时我用上了模拟退火,最后万万没想到MLE了

退火邪教诚不欺我

代码先放上:

#pragma GCC opitimize(2)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iomanip>
#include<cmath>
#include<ctime>
using namespace std;
#define re register int
#define I_LOVE_YOU cout<<ans<<'\n';//七夕限定 
const int N=1e5+5;
const double T=1e3;
const double cool=0.996;
const double mintemp=1e-10;
int n,w,tree[N<<2],maxx,ansx,ans;
struct Node{
	int x;
	int b;
}stars[N];
void add_data(int k,int l,int r,int x,int num)
{
	if(l==r)
	{
		tree[k]+=num;
		return;
	}
	int mid=(l+r)>>1;
	if(x<=mid)add_data(k<<1,l,mid,x,num);
	else add_data(k<<1|1,mid+1,r,x,num);
	tree[k]=tree[k<<1]+tree[k<<1|1];
}
int ask(int k,int l_now,int r_now,int l,int r)
{
	if(l>maxx)return 0;
	if(r>maxx&&l<=maxx)r=maxx;
	if(l<=l_now&&r_now<=r)return tree[k];
	int mid=(l_now+r_now)>>1,res=0;
	if(l<=mid)res+=ask(k<<1,l_now,mid,l,r);
	if(mid<r)res+=ask(k<<1|1,mid+1,r_now,l,r);
	return res;
}
inline void SA()
{
	double temp=T;
	while(temp>mintemp)
	{
		double nx;
		nx=ansx+(double)(rand()*2-RAND_MAX)*temp;
		if(nx<0)continue;
		nx=ceil(nx);
		int nans=ask(1,1,n,nx,nx+w-1);
		int dealt=nans-ans;
		if(dealt>0)
		{
			ansx=nx;
			ans=nans;
		}
		else if(exp((double)dealt/temp)>rand())ansx=nx;
		temp*=cool;
	}
}
int main()
{
	//freopen("P3353_2.in","r",stdin);
	//freopen("P3353.out","w",stdout);
	srand(time(NULL));srand(rand());
	ios::sync_with_stdio(false);
	memset(tree,0,sizeof(tree));
	cin>>n>>w;
	if(!w)
	{
		I_LOVE_YOU 
		return 0;
	}
	for(re i=1;i<=n;++i)
	{
		cin>>stars[i].x>>stars[i].b;
		maxx=max(maxx,stars[i].x);
	}
	for(re i=1;i<=n;++i)add_data(1,1,maxx,stars[i].x,stars[i].b);
	ansx=1;
	ans=ask(1,1,maxx,ansx,ansx+w-1);
	while((double)clock()/CLOCKS_PER_SEC<0.8)SA();
	I_LOVE_YOU
	return 0;
}

最后调试发现是退火里边“int nans=ask(1,1,n,nx,nx+w-1);”导致了MLE。也没有多余地消耗数组,百思不得其解,用了很多次函数会MLE吗?

2020/8/25 21:11
加载中...