bzoj 4412: [Usaco2016 Feb]Circular Barn

Posted lwq12138

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 4412: [Usaco2016 Feb]Circular Barn相关的知识,希望对你有一定的参考价值。

4412: [Usaco2016 Feb]Circular Barn

Description

有一个N个点的环,相邻两个点距离是1。点顺时针标号为1..N。
每一个点有ci头牛,保证∑ci=N。
每头牛都可以顺时针走。设一头牛走了d个单位停下了,将耗费d^2的能量。
请设计一种牛的走法,使得每一个点上都正好有一头牛,且最小化耗费的能量。

Input

第一行一个数N。N <= 100000
接下来N行,每行一个数ci。

Output

输出一个数表示耗费能量的最小值

Sample Input

10
1
0
0
2
0
0
1
2
2
2

Sample Output

33
题解:
所有奶牛只能往顺时针方向走,所以应该存在一个起点。
那么怎么找这个起点呢??
先把所有权值-1,然后我们考虑这样一个问题,若从x->y之间所有的奶牛都不会走出这个范围当且仅当不存在一个k,使得k->y权值为正,这个脑补一下吧。。。
那么这个起点就是这个环的最大子串和的起点,证明不讲了,然后就把环变成一条链,终点就是起点前一个。
最后是求最小值,这个也是有难度的。
由于(x+y)2>x2+y2
所以到某个点肯定会在中途换班,具体实现用个队列就好了。
#include<stdio.h>
#include<iostream>
using namespace std;
const int N=100005;
int n,i,s,l,x,t,w,a[N],g[N];
long long ans;
int main()
{
    scanf("%d",&n);
    for(i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        a[n+i]=a[i];
    }
    ans=0;x=1;
    for(i=1;i<=2*n-1;i++)
    {
        if(s<0) s=0,x=i;
        s+=a[i]-1;
        if(s>ans)
        {
            ans=s;
            l=x;
        }
    }
    t=1;w=0;ans=0;
    for(i=l;i<=l+n-1;i++)
    {
        while(a[i]--) g[++w]=i;
        ans+=1LL*(i-g[t])*(i-g[t]);
        t++;
    }
    cout<<ans;
    return 0;
}

 

以上是关于bzoj 4412: [Usaco2016 Feb]Circular Barn的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ4410: [Usaco2016 Feb]Fence in

BZOJ 3942: [Usaco2015 Feb]Censoring

[BZOJ2591][Usaco 2012 Feb]Nearby Cows

bzoj3940 [Usaco2015 Feb]Censoring

BZOJ 1651: [Usaco2006 Feb]Stall Reservations 专用牛棚

bzoj3940[Usaco2015 Feb]Censoring*