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 5using
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 ...