集訓隊日常訓練20181201 E 1005 : 小蝌蚪
阿新 • • 發佈:2018-12-01
時間限制(普通/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 } 12View Code} 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 }