Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 11910 | Accepted: 5215 |
Description
Input
Output
Sample Input
2 10 3 2 6 7 214 7 11 12 7 13 176 23 191
Sample Output
4 8 38 207
Source
分析:
①最短时间只需要找到位置最靠近杆中点的两个点,其中有陷阱(如果所有点都在中点的一侧),所以要求出这两个点到左右左右两边的最小距离的最大值。
②最长时间就是要看最后一只掉下去的Ant在棒子上呆的时间了:先给出几个结论:
a.最后一只蚂蚁一定是最中间的那一只;
b.最长时间情况下,这只蚂蚁会与其左右两边的蚂蚁碰面n-1次;
c.每次与其两边的蚂蚁碰面一次相当于把其最左边(右边)的那只蚂蚁赶下去。想象一下中间那只蚂蚁对两边使用隔山打牛,只有最边上的蚂蚁会接招,其他的蚂蚁只不过是在传递“能量”。这一段时间是可以推倒出来的,最终会得到一个常量(xr-xl)/2;也就是左右两边蚂蚁初始距离的一半,这就是赶走每一只蚂蚁的时间。
d.最后最后的那只蚂蚁自己也要下去了,由于他赶走别人的时间是常量,所以如果我们最终能够推倒出他最后的位置的话,那么我们就可以自主选定一个方向,使他从这开始往这个方向走的时间最长才掉下去,由此我们还要得出中间的蚂蚁最后会在哪一个位置。发现最终位置也是可以推倒的,就是x=(xr+xl)/2;由此只需要计算max(x, len-x)即可。
我的代码:
#include <iostream>
#include <algorithm>
using namespace std;
//[x, y)
int max(int x, int y) { return x > y ? x : y; }
int min(int x, int y) { return x < y ? x : y; }
const int Maxn = 1000000;
int pos[Maxn];
//make mistake : if all of ants is at one side of povit.
int mini(int len, int n)
{
int x = 0, y = n - 1;
int povit = len / 2;
while(x + 1 < y)
{
int m = (x + y) / 2;
if(pos[m] > povit) y = m;
else x = m;
}
//y must at the right of povit.
return max(min(len - pos[y], pos[y]), min(pos[x], len - pos[x]));
}
int main()
{
int t, l, n, i;
cin>>t;
while( t-- )
{
cin>>l>>n;
for(i = 0; i < n; i++) cin>>pos[i];
sort(pos, pos + n);
cout<<mini(l, n)<<" "<<max(pos[n-1], l - pos[0])<<endl;
}
return 0;
}
两次解决的,由于忽视了那个陷阱。
最后我有发现了一个更好的解决方案,其实我没有必要去开那个数组,方案如下。
- #include<iostream>
- #include<cstring>
- #include<algorithm>
- #include<cstdio>
- using namespace std;
- int main()
- {
- int n,l,cs,mx,mi,pos;
- cin>>cs;
- while(cs--)
- {
- mx=0,mi=0;
- cin>>l>>n;
- for(int i=0;i<n;i++)
- {
- cin>>pos;
- mx=max(mx,max(pos,l-pos));
- mi=max(mi,min(pos,l-pos));
- }
- cout<<mi<<" "<<mx<<endl;
- }
- return 0;
- }