NOI2010 超級鋼琴

2021-10-06 13:34:38 字數 899 閱讀 7520

題面

給定乙個序列 a[1-n] ,定義區間 [l,r] 的權值為 (l≤

r−l+

1≤r)

∑lra

[i

](l\le r-l+1\le r)\sum_l^ra[i]

(l≤r−l

+1≤r

)∑lr

​a[i

] ,現在求權值前k大的區間和它們權值的和

題解首先對於每個左端點 x ,他的右端點所在區間為 [x+l-1,x+r-1] 。而每個區間的權值,可以表示為 sum[r]-sum[l-1] 。所以對於每個左端點為x的區間,這些區間中權值的max為max

x+l−

1x+r

−1su

m[i]

−sum

[x−1

]max_^sum[i]-sum[x-1]

maxx+l

−1x+

r−1​

sum[

i]−s

um[x

−1],而st表可以o(1)處理出max

x+l−

1x+r

−1su

m[i]

max_^sum[i]

maxx+l

−1x+

r−1​

sum[

i]的值。

考慮建乙個堆,堆的元素表示為(x,l,r)的三元組,每次取出堆頂,把max

lrsu

m[i]

−sum

[x−1

]max_^sum[i]-sum[x-1]

maxlr​

sum[

i]−s

um[x

−1]加入答案,並把(x,l,t-1)和(x,t+1,r)壓入堆(t是使sum[i]最大的i)

不放**了。

NOI2010 超級鋼琴

傳送門 這個題有趣。巧妙地利用st表和堆 首先最暴力的我就不說了 第二個暴力就是主席樹 堆,預計得分70 80,時間o klog 2n std是用堆儲存可能的區間,然後用st表查詢區間最小值 因為其實如果知道區間右端點,再處理個字首和s 那麼就只要查詢區間最小值就可以了,可以st表o 1 做 inc...

NOI2010 超級鋼琴

求出字首和 對於每個結尾i,設現在取的區間是 j 1,i 則i r j i l,取出該區間sum j 的最小值,將sum i sum j 放入堆中 建立乙個大根堆,每次取出堆頂元素,將排名k 1,將sum i 區間第k小值放入堆中 求區間第k小可以用主席樹 直到取滿k次為止 include incl...

NOI2010 超級鋼琴

和有一道區間前k大異或很像。先求字首和,然後就變成右端點固定,取左端點的第k小問題,主席樹維護即可。並用堆維護前k個。ac pragma gcc optimize ofast funroll all loops include define int long long using namespace...