AGC 027 B Garbage Collector - 贪心

神仙题啊
题解:
显然每一趟是倒着往前捡。
首先把所有垃圾分开考虑:如果位置在 x x 的垃圾是第 i i 次被捡起来的,则对答案有 max ( 5 , 2 i + 1 ) \max(5,2i+1) 的贡献。原因考虑每次在已经捡起 i 1 i-1 个垃圾的情况下,捡起这个垃圾的增量。如果 i = 1 i=1 ,则一开始走到那里花费是 x x ,回去的代价是 ( 1 + 1 ) 2 x = 4 x (1+1)^2x=4x ,总共 5 x 5x 。否则,每单位距离会增加 ( i + 1 ) 2 i 2 = 2 i + 1 (i+1)^2-i^2=2i+1 的代价,路程是 x x ,因此总共增量是 ( 2 i + 1 ) x (2i+1)x
现在考虑要走 k k 趟,相当于是你有 k k 个第一次捡起的机会, k k 个第二次、 k k 个第三次…依次类推,要给每个垃圾分配是第几个被捡起的。显然 x x 越大则 i i 越小越好,也就是从远到近的分配1,2,…,前缀和优化一下即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define ldb long double
#define lint long long
#define N 200010
#define gc getchar()
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int a[N];lint s[N];
inline lint S(int a,int b) { return s[b]-s[max(a-1,0)]; }
int main()
{
	int n=inn(),X=inn();rep(i,1,n) s[i]=s[i-1]+inn();
	a[1]=5;rep(i,2,n) a[i]=2*i+1;ldb ans=1e100;
	rep(k,1,n)
	{
		ldb s=0ll;
		for(int i=n,j=1;i>0;i-=k,j++)
			s+=a[j]*S(i-k+1,i);
		ans=min(ans,s+(lint)X*(n+k));
	}
	return !printf("%lld\n",(lint)ans);
}

猜你喜欢

转载自blog.csdn.net/Mys_C_K/article/details/82770088