BZOJ4540 HNOI2016 序列 莫隊

2022-03-27 03:10:16 字數 2304 閱讀 2856

time limit: 20 sec  memory limit: 512 mb

給定長度為n的序列:a1,a2,…,an,記為a[1:n]。類似地,a[l:r](1≤l≤r≤n)是指序列:al,al+1,…,ar-

1,ar。若1≤l≤s≤t≤r≤n,則稱a[s:t]是a[l:r]的子串行。現在有q個詢問,每個詢問給定兩個數l和r,1≤l≤r

≤n,求a[l:r]的不同子串行的最小值之和。例如,給定序列5,2,4,1,3,詢問給定的兩個數為1和3,那麼a[1:3]有

6個子序列a[1:1],a[2:2],a[3:3],a[1:2],a[2:3],a[1:3],這6個子序列的最小值之和為5+2+4+2+2+2=17。

輸入檔案的第一行包含兩個整數n和q,分別代表序列長度和詢問數。接下來一行,包含n個整數,以空格隔開

,第i個整數為ai,即序列第i個元素的值。接下來q行,每行包含兩個整數l和r,代表一次詢問。

對於每次詢問,輸出一行,代表詢問的答案。

5 5

5 2 4 1 3

1 5

1 3

2 4

3 5

2 5

28 17

11 11

17 1 ≤n,q ≤ 100000,|ai| ≤ 10^9

題解:這道題我剛拿到手被打懵了……但其實這道題有明顯的2個特徵:

這樣的話我們就考慮一些離線的區間統計演算法,首先想到的大概都是莫隊。

那麼莫隊可行嗎?我們以從[l,r]轉移到[l,r+1]為例,考慮每一次端點移動時帶來的影響。如果這樣可做,其他三種情況肯定是類似的。

在移動之後,新增了[l,r+1],[l+1,r+1],[l+2,r+1],......,[r+1,r+1]這一些區間。

我們考慮新區間最小的數,設其為a[x],那麼,顯然有:

從[l,r+1]到[x,r+1]這些區間的最小值都不會是a[r+1],而[x+1,r+1]到[r+1,r+1]這些區間的最小值不確定

因此當轉移時,記錄變數ans+=(x-l+1)*a[x]+衛龍

那麼現在的問題是,衛龍是啥?怎麼計算?

不難看出,衛龍指的就是從[x+1,r+1]到[r+1,r+1]這些區間的最小值之和,如果直接對它暴力計算顯然不行,因此我們換一種思路。

設f[i]為以i為右端點的區間最小值之和,那麼對於上面所說的r和x,由於a[x]是區間最小值,故對於

任何y<=x,區間[y,x],[y,r+1]的最小值肯定不會發生變化,而如果y>x,我們已經在f裡加過了

那麼顯然 f[r+1]-f[x]就是我們要求的衛龍了因此得到轉移的式子ans+=(x-l+1)*a[x]+f[r+1]-f[x]

而對f陣列的計算可以遞推處理,設a[x]為左數第乙個小於a[i]的數,那麼有f[i]=f[x]+(i-x)*a[i]

正確性很顯然,在x以右的區間最小值一定是a[i],而由於x的性質,x及x左邊的區間最小值在區間右端點右移後也不會變化

這樣我們可以用乙個單調棧,在o(n)的時間內計算f陣列

這樣,這道題就可以做了,只要再把區間左端點移動的情況考慮一下,再計算乙個新的f1陣列表示以i為左端點的區間最小值之和即可

**見下:

1 #include 2 #include 3 #include 4 #include 5

using

namespace

std;

6 typedef long

long

ll;7

const

int n=100100;8

struct questq[n];

9int

n,m,len;

10int minpos[n][18],bin[20

],belong[n],stack[n];

11 ll a[n],l_f[n],r_f[n],ans[n],minv[n][18

];12 inline bool mt(const quest &a,const quest &b)

1317 inline void

intn()

1832

inti,top;

33for(i=1,top=0;i<=n;i++)

3439

for(i=n,top=0;i;i--)

4046

}47 inline int query(int l,int

r)48

53int

main()

5468

for(int i=1;i<=m;i++)

69 printf("

%lld\n

",ans[i]);

70 }

題解 bzoj4540 HNOI2016 序列

給定長度為n的序列 a1,a2,an,記為a 1 n 類似地,a l r 1 l r n 是指序列 al,al 1,ar 1,ar。若1 l s t r n,則稱a s t 是a l r 的子串行。現在有q個詢問,每個詢問給定兩個數l和r,1 l r n,求a l r 的不同子串行的最小值之和。例如...

bzoj 2326 HNOI2011 數學作業

題目大意 給你n,m,求concatenate 1.n mod m的值 concatenate 1.n 代表把1到n連起來 比如n 13時 concatenate 1.n 就是12345678910111213 n 10 1 m 10 9 這題很水,對於n,將其分開,比如145,就分成1 9,10 ...

BZOJ1010 HNOI2008 玩具裝箱toy

先把程式放著,週末來更新 華麗的分割線 不想寫題解了。照著網上的題解推一邊即可 注意有的題解最後推倒出來明明是求上 下 凸包的形式,但配的圖卻是下 上 凸包的。不過斜率優化還不是搞的很懂。time limit 1 sec memory limit 162 mb submit 6661 solved ...