新的学期到来了,王早已经把整个学期全都安排好了。
整个学期一共 n 天,第 i 天安排了 Pi 件事情。可是就在开学的前一天晚上,王突然觉得这个整个学期安排可能不够有趣。
一个学期是有趣当且仅当对于任意一个整数 i(1≤i≤n) ,第 i 天的的事情数目总是等于倒数第 i 天的事情数目。
因此王必须花费一定代价改变安排使得整个学期变得有趣。
王每次操作都花费一个代价,可以将一件事情从当天提前到昨天或者延后到明天。(第一天的事情不能提前,最后一天的事情不能延后)
请问王最小要花费多少的代价使得一个学期是有趣的?
比如,当 n=3,p1=2,p2=2,p3=0 时,
王可以先花费一个代价将第一天的一件事延后到第二天,就变成了 p1=1,p2=3,p3=0 。
再花费一个代价将第二天的一件事延后到第三天,就变成了 p1=1,p2=2,p3=1 。
显然, p1=1,p2=2,p3=1 是有趣的一个学期。花费的最小代价是 2 。
Input
一个整数 T ,表示数据组数。 (T<1000)
接下来 2×T 行。每组数据两行。
第一行一个整数 n ,表示盒子的个数。 (n<10000)
第二行 n 个整数,第 i 个整数 Pi 表示第 i 个天的最初的事件数。 (ai<10000)
Output
每组数据输出一个整数。表示王花费的最少代价。(如果王无论如何都不能达到目的,则输出-1
)
Sample input and output
Sample Input | Sample Output |
---|---|
3 2 0 1 3 1 3 2 5 1 0 0 0 0 | -1 1 2 |
解析
贪心,从两边往中间堆。每次比较对称的两个点,取小的那个作为基准。多出来部分往中间堆。
从首尾两边往中间扫,先比较第一个和最后一个,把多出来的事移到第二个(正数或者倒数),直到扫到中间。再特殊处理n的奇偶情况就可以了。
#include<cstdio>
using namespace std;
#define LOCAL
typedef long long LL;
LL N,P[10010];
void readdata()
{
scanf("%lld",&N);
LL sum=0;
for(int i=1;i<=N;i++) scanf("%lld",&P[i]),sum+=P[i];
if(!(N&1) && (sum&1)) {printf("-1\n");return;}
LL ans=0; LL d;
for(int i=1;i<=N>>1;i++)
if(P[i]!=P[N-i+1])
if(P[i]>P[N-i+1])
{
d=P[i]-P[N-i+1];
P[i]-=d;
P[i+1]+=d;
ans+=d;
}
else
{
d=P[N-i+1]-P[i];
P[N-i+1]-=d;
P[N-i]+=d;
ans+=d;
}
printf("%lld\n",(N&1)?ans:ans-d/2);
}
int main()
{
#ifdef LOCAL
freopen("D.in","r",stdin);
#endif
int T; scanf("%d",&T);
for(int i=1;i<=T;i++)
readdata();
#ifdef LOCAL
while(1);
#endif
return 0;
}