标签:
一天,冬马被春希和雪菜拉着去一起去游乐园玩。
经过了各种过山车的洗礼后,三人决定去坐摩天轮休息下。
这是一个巨大的摩天轮,每一个车厢能坐任意多的人。现在,等着坐摩天轮的有n个人(包含他们3人),摩天轮还有m个车厢可以坐人。每个人都有自己肥胖程度,出于某些原因,胖子和瘦子坐在同一节车厢就会产生一定的矛盾,这个矛盾的值为(MAX−MIN)2,其中MAX为当前车厢里面最胖的人的肥胖程度,MIN为最廋的那个人的肥胖程度。
爱管闲事的春希当然不希望就因为这点小事而使大家的这趟旅途不愉快,于是他决定帮大家安排怎么坐才能使总的矛盾值最小,希望你能帮他找到这个最小的矛盾值
第一行为两个整数n,m,分别表示人数和车厢数。(3≤n≤10000,1≤m≤5000)
第二行为n个整数,wi表示第i个人的肥胖程度。(0≤wi≤1000000)
每组数据,输出一个整数,为矛盾的最小值。(答案保证小于231)
Sample Input | Sample Output |
---|---|
4 2 4 7 10 1 |
18 |
解题报告
需要用到斜率优化,且空间复杂到可以优化到O(N) (是N还是M来着。。搞忘了,反正不是MN)
明天再更新了。。先上代码,空间复杂度是O(MN)的
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; const int maxn = 5000 + 15; int a[maxn*2],n,m,q[maxn*2],dp[maxn*2][maxn]; inline double Slope(int q,int w,int j) { if (a[q+1] == a[w+1]) return 1e233; return 1.0* (dp[q][j-1]+a[q+1]*a[q+1]-dp[w][j-1]-a[w+1]*a[w+1])/ (2*(a[q+1]-a[w+1])) ; } int main(int argc,char *argv[]) { scanf("%d%d",&n,&m); for(int i = 1 ; i <= n ; ++ i) scanf("%d",&a[i]); sort(a+1,a+1+n); a[n+1] = 0; // Just to Avoild Some Speical Situation -_= for(int i = 1 ; i <= n ; ++ i) dp[i][1] = (a[i]-a[1])*(a[i]-a[1]); for(int j = 2 ; j <= m ; ++ j) { int front = 0 , rear = 0; q[rear++] = 1; for(int i = 2 ; i <= n ; ++ i) { while(rear - front > 1 && Slope(q[front],q[front+1],j) <= a[i]) front++; dp[i][j] = dp[q[front]][j-1] + (a[i]-a[q[front]+1])*(a[i]-a[q[front]+1]); while(rear - front > 1 && Slope(q[rear-2],q[rear-1],j) >= Slope(q[rear-1],i,j)) rear--; q[rear++] = i; } } printf("%d\n",dp[n][m]); return 0; }
标签:
原文地址:http://www.cnblogs.com/Xiper/p/4455127.html