(題面來自acwing)
給定乙個長度為 n
'>n
的數列 a1,
a2,…
,an'>a1,a2,…,an
,每次可以選擇乙個區間 [l,r],使下標在這個區間內的數都加一或者都減一。
求至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列可能有多少種。
輸入格式
第一行輸入正整數n
'>n
。接下來n
'>n
行,每行輸入乙個整數,第i+1行的整數代表a
i'>ai
。輸出格式
第一行輸出最少操作次數。
第二行輸出最終能得到多少種結果。
資料範圍
0105
'>0≤a
i<
2147483648
'>0≤ai<2147483648(因為不開long long再次見到了祖宗)
0105
'>0≤a
i<
2147483648
'>看到題面之後的第一想法是差分之後暴搜方案,每次從(1~n + 1)選不同的兩個數+1/-1,目標狀態是d_2~d
0105
'>0≤a
i<
2147483648
'>_n全部為0。然而資料範圍顯然不能接受。考慮序列操作的本質:我們要將差分序列d中除第一項外全部變為0,顯然最優的方案是在d_2~d_n中
優先選擇乙個負數、乙個正數,分別+1、-1;設p、q分別為d中正、負項之和的絕對值,那麼如上的第一種操作會把p、q中較小的一方降為0,這個過程最多執行min(p, q)次。之後正/負項中有一方會有剩餘,我們可以選擇把d_1與剩餘項一同操作(相當於把原序列的某個字首全部+1/-1),也可以選擇d_(n+1)與剩餘項一同操作(相當於操作字尾),最終都可以實現d_2~d_n全部為0。這一步操作最多執行|p - q|次。那麼總的操作次數ans1滿足:
0105
'>0≤a
i<
2147483648
'>ans1 = min(p, q) + |p - q| = max(p, q)
第二問要求統計在滿足最小步數的情況下,可能產生的序列種類。由於最後序列每一項都相同,而d[1] = a[1],我們只要考慮最後d[1]有多少種即可。顯然,上述最短操作過程不分先後,並且第一種操作不會對d[1]產生影響。考慮執行第二種操作後d[1]可能的取值:d[1]最多被增加/減少|p - q|次,最少被操作0次,並且d[1]可以被操作[0, |p - q|]中的任意多次。因此d[1]的取值有|p - q| + 1種,即ans2 = |p - q| + 1。
**:#include
#include
#include
#define rep(i, a, b) for(int i = a; i <= b; ++i)
#define per(i, b, a) for(int i = b; i >= a; --i)
#define maxn 100010
using namespace std;
long long d[maxn], a[maxn];
int main()
cout << max(p, q) << endl << abs(p - q) + 1;
return 0;
}
AcWing 100 增減序列
給定乙個長度為 nn 的數列 a1,a2,ana1,a2,an,每次可以選擇乙個區間 l,r 使下標在這個區間內的數都加一或者都減一。求至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列可能有多少種。輸入格式 第一行輸入正整數nn。接下來nn行,每行輸入乙個整...
AcWing100 增減序列 差分
求出 a i 的差分數列 b i 題目的目的是使 b 2,ldots,b n 都變為 0 令 p,q 分別為 中正數和負數之和的絕對值,優先在 b 2,ldots,b n 中選一對正負數操作肯定是最優的,之後再分別與 b 1或b n 配對操作 include include include incl...
AcWing100 增減序列 差分 貪心
原題鏈結 題目要求通過對區間 l,r 的操作 1或者 1 使數列中數都一樣.我們發現滿足上述要求的數列的差分陣列的a 2 n 一定是 0,0,0,a 1 是val 據此,我們可以將問題轉化成經過最少次對區間 l,r 的操作使差分陣列a變為 val,0,0,0,下面是貪心的部分 大佬的部落格講解 in...