1. 程式人生 > >集訓隊日常訓練20181201 E 1005 : 小蝌蚪

集訓隊日常訓練20181201 E 1005 : 小蝌蚪

時間限制(普通/Java):500MS/1500MS     記憶體限制:65536KByte
總提交: 25            測試通過:5

描述

 

有 n 個裝著小蝌蚪的水缸排成一排,你擁有一個無限蝌蚪的袋子,可以往一個水缸裡放入一隻蝌蚪,也可以取出一隻蝌蚪,求最少的運算元,使得每個水缸的蝌蚪數量形成一個公差為 k 等差數列。

輸入

多組資料(<35),每組資料描述如下。

第一行一個數 n,k(1<=n<=105,0<=k=<104)。
第二行 n個數,表示每個水缸裡的蝌蚪數目(0<=ai

<=104)。

輸出

 

每組資料輸出一個最少操作次數。

樣例輸入

4 2
1 2 3 4
4 2
0 1 2 3

樣例輸出

4
6

提示

蝌蚪的個數不能為負。

題解:

最多進行多少次加減操作能使給定數列成為一個公差為k的等差數列(每次只能加或減1)

首先,先將第一個數假設為一個定值,然後改變後面的值,得到一個公差為k的等差數列,用一個數組b去記錄每一個數和它應得的數的差值,此時,對第一個數進行減x的操作,那麼後面每一位數都要進行減x的操作,也就是abs(b[i]-x),這個也就是每一位所要得到

應得值的次數,那麼只要從0迴圈到n每一位都進行上述操作得到的和就是最少操作次數,x取數列中位數的時候,和為最小。但是因為應得的值都必須是正數,所以得考慮x的值,使得最後得到的數列每一位都是正數。

 1 #include "bits/stdc++.h"
 2 #define ll long long
 3 using namespace std;
 4 inline void read(int &x)
 5 {
 6     x=0;char c=getchar();
 7     while(c<'0' || c>'9')c=getchar();
 8     while(c>='0' && c<='9'){
 9         x=x*10+c-'0';
10         c=getchar();
11     }
12
} 13 inline void write(int x) 14 { 15 int y=10,len=1; 16 while(y<=x) {y*=10;len++;} 17 while(len--){y/=10;putchar(x/y+48);x%=y;} 18 } 19 ll a[100001]; 20 ll b[100001]; 21 int main() 22 { 23 ll n,k; 24 while(~scanf("%I64d%I64d",&n,&k)) 25 { 26 scanf("%I64d",&a[0]); 27 //b[0]=a[0]; 28 int p=a[0]; 29 b[0]=0; 30 for(int i=1;i<n;++i) 31 { 32 scanf("%I64d",&a[i]); 33 //b[i]=b[i-1]+k-a[i]+b[i-1]; 34 b[i]=p+k-a[i]; 35 p+=k; 36 } 37 sort(b,b+n); 38 ll p1=a[0]; 39 ll res=0; 40 if(b[n/2]>p1)for(int i=0;i<n;++i)res+=abs(b[i]-p1); 41 else for(int i=0;i<n;++i)res+=abs(b[i]-b[n/2]); 42 printf("%I64d\n",res); 43 } 44 }
View Code