/*
ID: cjn77881
LANG: C++
TASK: skidesign
*/
//主要计算部分是O(n+m)级算法,预处理阶段使用了O(m*lgm)的排序
#include <stdio.h>
typedef struct Ski Ski;
struct Ski{
int l,r,Sl,Dl,Sr,Dr;
};
int N,idx,ans,val[1000];
Ski a[101];
void swap(int &a,int &b){
int x=a;
a=b;
b=x;
}
void qs(int *a,int h,int t){
if (h>=t) return;
int i=h,j=t,x=a[(h+t)>>1];
while (i<j){
while (a[i]<x) i++;
while (a[j]>x) j--;
if (i<=j){
swap(a[i],a[j]);
i++; j--;
}
}
qs(a,h,j);
qs(a,i,t);
}
int main(){
FILE *fin = fopen("skidesign.in","r");
FILE *fout = fopen("skidesign.out","w");
fscanf(fin,"%d\n",&N);
for (int i=0;i<N;i++) fscanf(fin,"%d\n",&val[i]);
qs(val,0,N-1);
idx=0;
for (int i=1;i<=100;i++){
a[i].l = a[i-1].l;
while (val[idx]<i && idx<N) {
a[i].l++;
idx++;
}
}
idx=N-1;
for (int i=99;i>=0;i--){
a[i].r = a[i+1].r;
while (val[idx]>i && idx>=0) {
a[i].r++;
idx--;
}
}
for (int i=1;i<=100;i++){
a[i].Sl=a[i-1].Sl+a[i].l;//高度i左侧的数,绝对值差的和
a[i].Dl=a[i-1].Dl+2*a[i-1].Sl+a[i].l;//高度i左侧的数,绝对值差的平方和
}
for (int i=99;i>=0;i--){ //右侧同上
a[i].Sr=a[i+1].Sr+a[i].r;
a[i].Dr=a[i+1].Dr+2*a[i+1].Sr+a[i].r;
}
ans=2147483647;
for (int i=0;i<=100;i++){ //长度为17的区间左右两侧的差值平方和最小
if ((i+17<=100) && (a[i].Dl+a[i+17].Dr<ans)){
ans=a[i].Dl+a[i+17].Dr;
idx=i;
//printf("idx=%d Dl=%d Dr=%d ans=%d\n",i,a[i].Dl,a[i+17].Dr,ans);
}
}
//for (int i=0;i<101;i++) printf("%d l=%d r=%d Sl=%d Dl=%d Sr=%d Dr=%d\n",i,a[i].l,a[i].r,a[i].Sl,a[i].Dl,a[i].Sr,a[i].Dr);
printf("%d\n",ans);
fprintf(fout,"%d\n",ans);
return 0;
}
USACO 1.4.6_skidesign
最新推荐文章于 2021-02-16 16:04:53 发布