1. 程式人生 > >【貪心】[USACO2016 金組]Circular Barn

【貪心】[USACO2016 金組]Circular Barn

題目描述

Being a fan of contemporary architecture, Farmer John has built a new barn in the shape of a perfect circle. Inside, the barn consists of a ring of nn rooms, numbered clockwise from 1…n1…n around the perimeter of the barn (3≤n≤100,0003≤n≤100,000). Each room has doors to its two neighboring rooms, and also a door opening to the exterior of the barn.
Farmer John owns nn cows, and he wants exactly one cow to end up in each room in the barn. However, the cows, being slightly confused, line up at haphazard doors, with possibly multiple cows lining up at the same door. Precisely cici cows line up outside the door to room ii, so ∑ci=n∑ci=n.

To manage the process of herding the cows so that one cow ends up in each room, Farmer John wants to use the following approach: each cow enters at the door at which she initially lined up, then walks clockwise through the rooms until she reaches a suitable destination. Given that a cow walking through dd doors consumes d2d2 energy, please determine the minimum amount of energy needed to distribute the cows so one ends up in each room.

INPUT FORMAT (file cbarn.in):

The first line of input contains nn. Each of the remaining nn lines contain c1…cnc1…cn.

OUTPUT FORMAT (file cbarn.out):

Please write out the minimum amount of energy consumed by the cows.

SAMPLE INPUT:

10
1
0
0
2
0
0
1
2
2
2

SAMPLE OUTPUT:

33
題目大意,給定一個環長為n的環上每個點上有a

i只牛,每隻牛可以在環上順時針移動,代價為移動距離的平方,問將環上每個節點上都有一隻牛的代價是多少

題目解析

可以發現我們如果需要移動ij(j>i)到達kp(p>k)的話我們有i>k同時j>p那麼我們就有對於任意的j=k同樣滿足,那麼我們貪心處理一下,對於每一次迴圈到當前位置,如果我們有當前位置有可以出發的奶牛那麼一定出發(更優)然後扔下一隻佇列中距離最遠的,沒有就扔下一隻繼續走。

程式碼

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int MAXN = 100000;
int a[MAXN+10], c[MAXN+10];
char ch;
void Read(int &s){
    while((ch=getchar()),ch<'0'||ch>'9');
    s = ch-'0';
    while((ch=getchar()),ch>='0'&&ch<='9')
        s = s*10+ch-'0';
    ungetc(ch, stdin);
}
int main(){
    int n;
    Read(n);
    for(int i=1;i<=n;i++){
        Read(c[i]);
        a[i] = i;
    }
    queue<int> que;
    long long ans = 0;
    for(int i=1;i<=n;i++){
        if(!que.empty()){
            int u = que.front();
            que.pop();
            ans += 1LL*(i-u)*(i-u);
            a[i] = u;
            c[i] ++;
        }
        for(;c[i]>1;c[i]--) que.push(i);
    }
    int tn = n*2;
    for(int i=n+1;i<=tn;i++){
        if(!que.empty()){
            if(c[i-n]){
                que.push(a[i-n]+n);
                ans -= 1LL*(i-n-a[i-n])*(i-n-a[i-n]);
            }
            int u = que.front();
            que.pop();
            ans += 1LL*(i-u)*(i-u);
        }
    }
    printf("%lld\n", ans);

    return 0;
}