圆圈舞蹈

圆圈舞蹈

【问题描述】
熊大妈的奶牛在时针的带领下,围成了一个圆圈跳舞。由于没有严格的教育,奶牛们之间的间隔不一致。
奶牛想知道两只最远的奶牛到底隔了多远。奶牛A到B的距离为A顺时针走和逆时针走,到达B的较短路程。告诉你相邻两个奶牛间的距离,请你告诉奶牛两只最远的奶牛
到底隔了多远。
【输入】
第一行一个整数N,表示有N只奶牛。(2≤N≤100000)
接下来2~N+1行,第I行有一个数,表示第I-1头奶牛顺时针到第I头奶牛的距离。(1≤距离≤maxlongint,距离和≤maxlongint)
第N+l行的数表示第N头奶牛顺时针到第1头奶牛的距离。
【输出】
一行,表示最大距离。

暴力算法我就不打了 应该能过一些数据

二分算法
用前缀和将环一分为二,再枚举答案。
大概二分是一个很咸的东西啦
把这个圆顺时针做前缀和,肯定越对面距离越大,然后枚举两边的值并比较即可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;

int sum[200010],a[200010],n,l,r,x,mid,y,maxx,minx,tmp;

int main()
{
    freopen("circle.in","r",stdin);
    freopen("circle.out","w",stdout);
    scanf("%d",&n);
    for (int i=2; i<=n+1; i++)
      {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
      }
    for (int i=n+2; i<=2*n; i++)
      sum[i]=sum[n+1]+sum[i-n];
    maxx=0;
    for (int i=1; i<=n; i++)
      {
        l=i; r=n+i;
        minx=2147000000;
        while (l<=r)
          {
            mid=(l+r)>>1;
            x=sum[mid]-sum[i];
            y=sum[n+i]-sum[mid];
            if (fabs(x-y)<minx) 
              {
                minx=fabs(x-y);
                if (x<y) tmp=x; else tmp=y;
                if (tmp>maxx) maxx=tmp;
              }
            if (l==mid) break;
            if (x<y) l=mid; else r=mid; 
          }
          x=sum[r]-sum[i];
          y=sum[n+i]-sum[r];
          if (fabs(x-y)<minx)
            {
                minx=fabs(x-y);
                if (x<y) tmp=x; else tmp=y;
                if (tmp>maxx) maxx=tmp;
            }
      }
      cout<<maxx;
}

o(n)算法
我觉得这个还是蛮微妙的
emmm

可以把这个圆看作一条直线
设立一个l,一个r分别指向这条直线,l到r之间的距离为x
那么最右值肯定是越靠近总和除以2越好
1 2 3 4 5 … n
l r
那么,当x小于sum/2时,r往右靠,(一遍做一边打擂),如果x大于sum/2,那么l向右靠,当r到n时,循环结束,答案得出
是是不是有点神奇!!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
long long n,sum=0,ans=0;
long long a[100100];
int main()
{
    freopen("circle.in","r",stdin);
    freopen("circle.out","w",stdout);
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]),a[i]+=a[i-1];
    sum=a[n];
    int l=1,r=2;
    while(l<r && r<=n)
    {
        long long res1=a[r]-a[l],res2=sum-res1;
        ans=max(ans,min(res1,res2));
        if(res1>res2) l++;
        else r++;
    }
    printf("%lld",ans);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/beautiful_cxw/article/details/80960517