【bzoj3043】IncDec Sequence 差分
阿新 • • 發佈:2017-10-24
整數 ... font 結果 兩個 ++ pre span cnblogs
題目描述
給定一個長度為n的數列{a1,a2...an},每次可以選擇一個區間[l,r],使這個區間內的數都加一或者都減一。
問至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列有多少種。
輸入
第一行一個正整數n
接下來n行,每行一個整數,第i+1行的整數表示ai。
輸出
第一行輸出最少操作次數
第二行輸出最終能得到多少種結果
樣例輸入
4
1
1
2
2
樣例輸出
1
2
題解
差分
把原序列差分,考慮所有的$a_i-a_{i-1}(1\le i\le n+1)$,當$i\neq1$且$i\neq n+1$是都需要等於0。因此統計一下需要加多少次、減多少次。由於要求操作次數最少,因此其中的加減需要抵消。
即如果有$s1$次減操作、$s2$次加操作,那麽需要有$min(s1,s2)$次操作選出其中的兩個抵消。由於是差分數組,對應到原序列中就是區間+1或-1。
剩下的操作可以選擇用$a_1-a_0$或者$a_{n+1}-a_n$。選擇$a_1-a_0$的話相當於序列的值改變,否則不改變。因此序列改變的範圍是$[0,|s1-s2|]$,取值的範圍再+1即可。
因此只需要統計出每一個數與前一個數差了多少即可。
時間復雜度$O(n)$
#include <cstdio> typedef long long ll; int main() { int n , i; ll x , y , s1 = 0 , s2 = 0; scanf("%d%lld" , &n , &x); for(i = 2 ; i <= n ; i ++ ) { scanf("%lld" , &y); if(x < y) s1 += y - x; else s2 += x - y; x = y; } if(s1 < s2) printf("%lld\n%lld\n" , s2 , s2 - s1 + 1); else printf("%lld\n%lld\n" , s1 , s1 - s2 + 1); return 0; }
【bzoj3043】IncDec Sequence 差分