NOIP2012模拟试题【圆圈舞蹈( circle)
2.圆圈舞蹈( circle)
【问题描述】
熊大妈的奶牛在时针的带领下,围成了一个圆圈跳舞。由于没有严格的教育,奶牛们之间的间隔不一致。
奶牛想知道两只最远的奶牛到底隔了多远。奶牛A到B的距离为A顺时针走和逆时针走,到达B的较短路程。告诉你相邻两个奶牛间的距离,请你告诉奶牛两只最远的奶牛
到底隔了多远。
【输入】
第一行一个整数N,表示有N只奶牛。(2≤N≤100000)
接下来2~N+1行,第I行有一个数,表示第I-1头奶牛顺时针到第I头奶牛的距离。(1≤距离≤maxlongint,距离和≤maxlongint)
第N+l行的数表示第N头奶牛顺时针到第1头奶牛的距离。
【输出】
一行,表示最大距离。
【样例】
Circle.in
5
1
2
3
4
5
Circle.out
7
【样例解析】
Circle.out所有奶牛I到J之间的距离和到达方式(顺为顺时针,逆为逆时针)如下:
I\J |
1 |
2 |
3 |
4 |
5 |
1 |
O |
1 (顺) |
3(顺) |
6(顺) |
5(逆) |
2 |
1(逆) |
O |
2(顺) |
5(顺) |
6(逆) |
3 |
3(逆) |
2(逆) |
0 |
3(顺) |
7(顺) |
4 |
6(逆) |
5(逆) |
3(逆) |
0 |
4(顺) |
5 |
5(顺) |
6(顺) |
7(逆) |
4(逆) |
0 |
所以,最远的两头奶牛为3到5,距离是7。
分析样例(手写样例)时我们发现,最远距离总是接近圆圈周长的一半,对此我们可以证明
因为奶牛A到B的距离为A顺时针走(dis)和逆时针走(ddis),到达B的较短路程,逆时针走(ddis)等于圆圈周长(sum)减去顺时针走的路程(dis),所以最远距离即求 min(sum-dis,dis) 的最大值
什么时候最大?
显然,当dis最接近sum/2时。
因此我们只需要求得每个点的最远距离即可解答=v=
下面是寻找每个点的最远距离的过程
(蓝字表示dis)
首先是1号点(o゜▽゜)o☆
当到达4号点时,dis=6;当到达5号点时,dis=10;
因此又引出一个细节:因为我们寻找的总是折中的点,所以要比较它和它相邻的点分别到起点的距离;
距离1号点最远的是4号点
当寻找起点为2号点的最远距离时,简单的方法是将起点顺时针移动,如果距离未达到sum/2,就将终点也顺时针移动
寻找完后,dis=6-1+4=9,距离是6,与1号点的最远距离比较,最远距离不变依然为6
重复上述步骤,最终最远距离为起点是3号点,终点是5号点的距离,即7
(っ*´Д`)っ下面放出代码
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<ctime> 5 #include<algorithm> 6 using namespace std; 7 int n; 8 long long sum; 9 long long l[100001]; 10 long long dis; 11 void work() 12 { 13 int u=0; 14 int v=0; 15 dis=0; 16 long long ans=0; 17 int j; 18 for(int i=1;i<=n;i++)//寻找距离一号点最远的点 19 { 20 dis+=l[i-1];//*** 21 if(dis>sum/2) 22 { 23 j=i;//记录这个点 24 break; 25 } 26 } 27 ans=max(ans,min(sum-dis,dis));//因为我们寻找的是折中的点,所以需要比较两次,即它和它相邻的点; 28 ans=max(ans,min(dis-l[j-1],sum-dis+l[j-1])); 29 for(int i=2;i<=n;i++) 30 { 31 dis=dis-l[i-1];//寻找第i个点的最远距离,将起点从上一个点顺时针移动 32 while(dis<sum/2) 33 { 34 dis+=l[j+1]; 35 j++;//终点也顺时针移动 36 } 37 ans=max(ans,min(sum-dis,dis));//与上面同理 38 ans=max(ans,min(sum-dis+l[j-1],dis-l[j-1])); 39 } 40 printf("%lld ",ans); 41 } 42 void read() 43 { 44 scanf("%d",&n); 45 for(int i=1;i<=n;i++) 46 { 47 scanf("%lld",&l[i]); 48 sum+=l[i];//记录圆圈周长 49 } 50 } 51 int main() 52 { 53 freopen("circle.in","r",stdin); 54 freopen("circle.out","w",stdout); 55 //clock_t start=clock(); 56 read(); 57 work(); 58 //clock_t end=clock(); 59 //printf("%d %d",start,end); 60 return 0; 61 }