BZOJ4409: [Usaco2016 Feb]Circular barn

这一道题的话因为满足抉择单调性然后Claris说可以暴力(二分求分界点
太神了!!

#include<cstdio>
#include<cstring>
#include<cstdlib>

using namespace std;
char c;
inline void read(int &a)
{
    a=0;do c=getchar();while(c<'0'||c>'9');
    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
#define ll long long
const
  ll INF=1ll<<61;
int base;
int ned[2002];
ll a[2002],b[2002];
ll *f,*g,*wa;
void DFS(int l,int r,int start,int end)
{
    int mid=(l+r)>>1;
    int i,M;
    ll tp1,tp2=INF;
    for(i=start;i<mid&&i<=end;i++)
      {
        tp1=g[i]-a[mid]+a[i]+(b[mid]-b[i])*mid;
        if(tp1<tp2)tp2=tp1,M=i;
      }
    f[mid]=tp2;
    if(l<mid)DFS(l,mid-1,start,M);
    if(r>mid)DFS(mid+1,r,M,end);
}
int main()
{
    f= new ll[2002];
    g= new ll[2002];
    int i,j,n,k;    
    ll ans=INF;
    read(n),read(k);    
    for(i=n;i;i--)read(ned[i]),ned[i+n]=ned[i];
    for(i=1;i<=n+n;i++)a[i]=a[i-1]+ned[i]*i,b[i]=b[i-1]+ned[i];
    for(i=1;i<=n;i++)
    {
        g[i-1]=0;
        for(j=i;j<i+n;j++)g[j]=INF;
        for(j=1;j<=k;j++)
           {
             DFS(i,i+n-1,i-1,i+n-1);

             wa=g,g=f,f=wa;
           }
        if(g[i+n-1]<ans)ans=g[i+n-1];
    }
    printf("%lld",ans);
    return 0;
}

你可能感兴趣的:(BZOJ4409: [Usaco2016 Feb]Circular barn)