bzoj 3043 數列操作(差分)

2021-08-10 09:22:29 字數 1243 閱讀 5306

題目描述

給定乙個長度為n的數列,每次可以選擇乙個區間[l,r],使這個區間內的數都加一或者都減一。

問至少需要多少次操作才能使數列中的所有數都一樣,並求出在保證最少次數的前提下,最終得到的數列有多少種。

輸入格式

第一行乙個正整數n 接下來n行,每行乙個整數,第i+1行的整數表示ai。

輸出格式

第一行輸出最少操作次數 第二行輸出最終能得到多少種結果

樣例資料

input

4 1

1 2

2 output

1 2

資料規模與約定

對於100%的資料,n=100000,0<=ai<2147483648。

時間限制:

1s 1s

空間限制:

256mb

數列的差分是什麼?就是相鄰兩項求差。我們令原數列為a,差分數列為d,那麼就有d1

=a1,

di=a

i−ai

−1(2

≤i≤n

),dn

+1=0

我們如果要將[l

,r] 內的數都+1/-1」只需要:dl

+1並且把dr

+1−1

(其他操作類同)。我們最終要達到的結果是:所有a數列的元素都是相等的,自然相鄰元素的差就是0。di

=0(2

≤i≤n

) ,最後數列中僅存在的數值即為d1

, 要將d數列中第二項至第n項全部變為0並使操作次數最少,首先我們將每個負數和每個正數配對執行操作,設d數列中第2至第n項所有正數分別求和得到的值為pos,負數分別求和得到的值的絕對值為neg,這一步的操作次數即為mi

n 。此時還剩餘和的絕對值為ab

s(p−

q)的數沒有變為0,

每次操作我們可以將其與d1

或dn+

1 配對進行操作,操作次數為abs(p-q)。

#include

#define maxn 102000

using

namespace

std;

inline

int read()

int n,a[maxn];

long

long pos,neg;

int main()

區間操作 差分

link description 對於乙個初始值全為0的序列,每次操作可以對乙個 l,r l,r l,r 區間的值全部加1,問最少多少次操作達到a aa,並由字典序從小到大輸出方案 解題思路 差分陣列,對於每次操作相當於乙個 1 1 1和 1 1 1操作,我們記錄下每次 1 1 1的位置和 1 1 ...

bzoj 3631 (樹上差分)

給你一棵有n n個結點的樹,現在給你乙個大小為n n的排列,說明你的行走路徑。你每經過樹上的每乙個點,你就需要將這個點的點權加1。問你最後所有點的點權大小。根據題目的意思,很明顯這道題是乙個非常典型的點差分的問題。我們只需要對結點uiu i vi vi 以及lca ui,vi l ca u i v ...

bzoj 4390(樹上差分)

給你一顆有n n個結點的樹以及m m個路徑。對於每乙個路徑pat hipa thi 代表著你將會從uiu i 走到vivi 現在問你,你走完著m m個路徑後,在這n n個結點中經過的最多的次數。首先,如果我們用dfs dfs在樹上暴力去跑的話,顯然時間肯定是接受不了的。因此我們需要考慮一種較為優美的...