設$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#includeview code#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;
}
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...