题解 P3132 【[USACO16JAN]愤怒的奶牛Angry Cows】

· · 题解

实际上楼下的题解还是可以继续优化的, 因为f与x的差都具有单调性,而答案去其中的最大值,所以对于j>i,f[j]的最优决策点一定在f[i]的决策点的右边,所以就可以利用这个性质优化了。 时间复杂度O(n)(除开排序) 下面贴代码(f1对应楼下g)

#include<cstdio>
#include<algorithm>
using namespace std;
 long n,x[50001],f[50001],f1[50001],ans=0x3f3f3f3f,l,r,now;
 bool ans1;
int main()
{
freopen("a.in","r",stdin);
 scanf("%ld",&n);
 for(int i=1;i<=n;i++)
  scanf("%ld",&x[i]);
 sort(x+1,x+n+1);
 f[1]=0;
 now=1;
 for(int i=2;i<=n;i++)
  {
   while(x[i]-x[now]>=f[now]+1&&now<i-1) now++;
   if(f[now]+1>x[i]-x[now-1])
    now--;
   f[i]=max(f[now]+1,x[i]-x[now]);
  }
 f1[n]=0;now=n;  
 for(int i=n-1;i>=1;i--)
 {
  while(x[now]-x[i]>=f1[now]+1&&now>i+1) now--;
  if(f1[now]+1>x[now+1]-x[i]&&now<n) now++;
  f1[i]=max(f1[now]+1,x[now]-x[i]);
 }
 now=1;
 for(int i=1;i<=n;i++)
 {
 l=r;
  while(x[i]-x[now]>=(f[now]+1)*2&&now<i-1) 
   now++;
  if(x[i]-x[now-1]<(f[now]+1)*2) now--;
  if(max(f1[i]+1,max(f[now]+1,(x[i]-x[now])/2))<ans||(max(f1[i]+1,max(f[now]+1,(x[i]-x[now])/2))==ans&&((x[i]-x[now])%2<ans1)))
   {
   ans=max(f1[i]+1,max(f[now]+1,(x[i]-x[now])/2));
   if((x[i]-x[now])/2>=f[now]+1&&(x[i]-x[now])/2>=f1[i]+1)
   ans1=(x[i]-x[now])%2;
  else ans1=0;
 }
 }
  printf("%ld",ans);
  if(ans1)
   printf(".5");
   else printf(".0");
 return 0;
}

因为我写得丑,才跑了142ms(rank1写的似乎是nlogn的)