NOI2010 超級鋼琴

2022-03-02 10:17:59 字數 1220 閱讀 2841

設$s_i=\sum\limits_^i a_j$,那麼相同左端點$l$的區間之中,最大的區間和就是$\mathop\limits_^\\}=\mathop\limits_i\-s_$。

那對字首和做st表就可以快速求解了。

設$f(i,l,r,t)$表示左端點是$i$,右端點在$[l,r]$範圍內,使區間和最大的區間右端點是$t$,的最大區間和。

那我們可以把所有的$f(i,i+l-1,i+r-1,t)$丟進堆裡,取$k$次,每次把右端點區間按$(l,t-1)$和$(t+1,r)$分開重新壓進堆裡。

**(100分):

#include#include

#include

#include

#include

#include

#include

#include

#include

#define il inline

#define rg register

#define _1 first

#define _2 second

using

namespace

std;

typedef

long

long

ll;const

int n=5e5;

const

int l=18

;

intn,k,llim,rlim;

ll a[n+3],s[n+3

];

int lg2[n+3

];

int f[n+3][l+3

];

il void

init()

}il

int qry(int l,int

r)struct

dat dat(

int i,int l,int r,int

k) :i(i),l(l),r(r),k(k){}

};il

bool

operator

priority_queue

hp;int

main()

ll ans=0

;

while(k--)

printf(

"%lld

",ans);

return0;

}

view code

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