題面
給定乙個序列 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...