[题解]CQOI2012 T2 组装 assemble

组装 assemble

【题目描述】

数轴上有m个生产车间可以生产零件。一共有n种零件,编号为1~n。第i个车间的坐标为xi,生产第pi种零件(1<=pi<=n)。你需要在数轴上的某个位置修建一个组装车间,把这些零件组装起来。为了节约运输成本,你需要最小化cost(1)+cost(2)+…+cost(n),其中cost(x)表示生产第x种零件的车间中,到组装车间距离的平方的最小值。

【输入】

 

输入第一行为两个整数n, m,即零件的种类数和生产车间的个数。以下m行每行两个整数xi和pi(1<=pi<=n)。输入按照生产车间从左到右的顺序排列(即xi<=xi+1。注意车间位置可以重复)。输入保证每种零件都有车间生产。

【输出】

输出仅一行,即组装车间的最优位置(可以和某个生产车间重合),四舍五入保留四位小数。输入保证最优位置惟一。

【样例】

assemble1.in

3 5

-1 3

0 1

2 3

4 2

5 2

assemble1.out

2.0000

 

assemble2.in

4 8

-10 2

-8 1

-5 1

-1 3

3 4

4 3

6 2

9 4

assemble2.out

0.7500

【数据规模】

编号 1-4 5-10
n <=15 <=10000
m <=25 <=100000
xi <=100 <=100000

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------

【题解】

    还是一道比较简单的题目,感觉是在考数感。。注意题目要求的最终答案相当于是使选出的n个数的方差的n倍最小的位置。对于方差由两个公式,这里我用的第二个公式,方便维护。给出维基上方差的链接:http://zh.wikipedia.org/wiki/%E6%96%B9%E5%B7%AE

    用一个结构体数组a[]保存一个伪链表。包括两个关键字,第一个为生产某种零件的车间位置,第二关键字为生产同种零件的下一个车间的位置。然后排序,按照两个关键字之和从小到大排序,即按照它们的终点坐标排序。(为什么自己想)默认第一次选出的n个车间为生产每一种零件的第一个车间,计算出总花费以及位置,然后从前往后扫a[],依次改变某一个车间的位置,更新总花费。

    不多赘述了,个人认为代码写得还不错。望引玉>_<

 1 #include<iostream> 
 2 #include<cstdio> 
 3 #include<cstring> 
 4 #include<algorithm> 
 5 using namespace std; 
 6 #define MAXM 100020 
 7 #define MAXN 10020 
 8 typedef long long llt; 
 9 int n,m; 
10 struct node 
11 { 
12     llt x,next; 
13 }; 
14 node a[MAXM]; 
15 int In; 
16 int Pos[MAXN],INF; 
17 llt Sum1,Sum2; 
18 bool Cmp(node a,node b) 
19 { 
20     return (a.x+a.next)<(b.x+b.next); 
21 } 
22 inline void Get_int(int &Ret) 
23 { 
24     char ch; 
25     bool flag=false; 
26     for(;ch=getchar(),ch<'0'||ch>'9';) 
27         if(ch=='-') 
28             flag=true; 
29     for(Ret=ch-'0';ch=getchar(),ch>='0'&&ch<='9';Ret=Ret*10+ch-'0'); 
30     flag&&(Ret=-Ret); 
31 } 
32 void Read() 
33 { 
34     Get_int(n); 
35     Get_int(m); 
36     int i,xi,pi; 
37     memset(Pos,0x3f,sizeof(Pos)); 
38     INF=Pos[0]; 
39     for(i=1;i<=m;i++) 
40     { 
41         Get_int(xi); 
42         Get_int(pi); 
43         if(Pos[pi]==INF) 
44         { 
45             Sum1+=xi; 
46             Sum2+=xi*xi; 
47         } 
48         else
49         { 
50             a[++In].x=Pos[pi]; 
51             a[In].next=xi; 
52         } 
53         Pos[pi]=xi; 
54     } 
55     sort(a+1,a+1+In,Cmp); 
56 } 
57 void Work() 
58 { 
59     //fang cha >_< _______orz 
60     llt tmp=(llt)n*Sum2-Sum1*Sum1,_tmp; 
61     //tmp=Sum2-(Sum1/n*Sum1/n)*n; 
62     llt ans=Sum1; 
63     //ans=Sum1/n; 
64     int i; 
65     for(i=1;i<=In;i++) 
66     { 
67         if(a[i].x==a[i].next) 
68             continue; 
69         Sum1+=(a[i].next-a[i].x); 
70         Sum2+=(a[i].next*a[i].next-a[i].x*a[i].x); 
71         _tmp=n*Sum2-Sum1*Sum1; 
72         if(tmp>_tmp) 
73         { 
74             tmp=_tmp; 
75             ans=Sum1; 
76         } 
77     } 
78     printf("%.4lf\n",(double)ans/(double)n); 
79 } 
80 int main() 
81 { 
82     //freopen("assemble.in","r",stdin); 
83     //freopen("assemble.out","w",stdout); 
84     Read(); 
85     Work(); 
86     return 0; 
87 } 

 

 

 

posted @ 2013-01-14 21:58  zyy是一只超级大沙茶  阅读(418)  评论(0编辑  收藏  举报