斜率优化悬关求调
查看原帖
斜率优化悬关求调
377873
EricWan楼主2024/7/12 16:42

11 pts,应该只过样例。

这份代码已经制伏 7 个人了

#include <bits/stdc++.h>
#define MAXN 2000005
#define int long long
using namespace std;
struct dequeue
{
	int begin, end;
	double tp[MAXN], b[MAXN];
	int k[MAXN];
	int size()
	{
		return end - begin + 1;
	}
	void push_back(double nowtp, int nowk, double nowb)
	{
		end++;
		tp[end] = nowtp;
		k[end] = nowk;
		b[end] = nowb;
	}
	void pop_back()
	{
		end--;
	}
	void pop_front()
	{
		begin++;
	}
} q;
double turnpoint(int k1, double b1, int k2, double b2)
{
//	cout << "turnpoint(" << k1 << "," << b1 << "," << k2 << "," << b2 << ") = " << (b2 - b1) / (k1 - k2) << endl;
	return (b2 - b1) / (k1 - k2);
}
int n;
double x[MAXN], p[MAXN], c[MAXN], sxp[MAXN], sp[MAXN], f[MAXN];
signed main()
{
	q.begin = 1;
	q.push_back(-1, 0, 0);
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		cin >> x[i] >> p[i] >> c[i];
		sxp[i] = sxp[i - 1] + x[i] * p[i];
		sp[i] = sp[i - 1] + p[i];
		
		int nowb = x[i] * sp[i] - sxp[i] + c[i];
		while (q.size() > 1 && q.tp[q.begin + 1] < x[i])
		{
//			cout << q.tp[q.begin + 1] << endl;
			q.pop_front();
		}
		f[i] = nowb + q.k[q.begin] * x[i] + q.b[q.begin];
//		cout << nowb << " " << q.k[q.begin] << " " << q.b[q.begin] << endl;
		int newk = - sp[i];
		double newb = sxp[i] + f[i];
		double nowtp = turnpoint(newk, newb, q.k[q.end], q.b[q.end]);
		while (q.size() > 1)
		{
			if(newk==q.k[q.end]){
				if(newb<q.b[q.end])break;
				q.pop_back();continue;
			}
			
			nowtp = turnpoint(newk, newb, q.k[q.end], q.b[q.end]);
			
			if (nowtp > q.tp[q.end])
			{
				break;
			}
			if(newb!=q.b[q.end])q.pop_back();
		}
		q.push_back(nowtp, newk, newb);
//		cout << f[i] << " " << newk << " " << newb << " " << q.size() << endl;
	}
	f[0] = 1e18;
	for (int i = n; i >= 0; i--)
	{
		f[0] = min(f[i], f[0]);
		if (p[i])
		{
			break;
		}
	}
	cout << f[0];
	return 0;
}
2024/7/12 16:42
加载中...