P2048 超级钢琴(RMQ)
目录
Description
从 n 个数中,挑选出 k 个长度为 [L, R] 的子段,使得他们的子段之和最大,输出总的最大值
State
\(1<=n<=5*10^{5}\)
\(1<=k<=5*10^5\)
\(1<=L<=R<=n\)
\(-1000<=a[i]<=1000\)
Input
4 3 2 3
3
2
-6
8
Output
11
Solution
想要枚举所有满足长度的子段显然是不合理的,但是对于每一个 \(i\) 都有 \(x∈[i + L - 1, i +R - 1]\) ,使得 \(\sum_{i}^xa[i]\) 最大,下一次的时候将区间分为 \(x∈[L,x-1]\) 和 \(x∈[x+1,R]\) 这两个区间就可以了
Code
const int N = 5e5 + 5;
ll n, m, _;
int i, j, k;
int a[N];
int sum[N];
struct Node
{
int l, r;
int maxx;
int id;
#define lson id << 1
#define rson id << 1 | 1
Node(){}
Node(int maxx):maxx(maxx){}
friend Node max(Node a, Node b){
Node ans(-2e9);
if(a.maxx > b.maxx){
ans = a;
}
else{
ans = b;
}
return ans;
}
}t[N << 2];
void push_up(int id)
{
int L = t[id].l, R = t[id].r;
t[id] = max(t[lson], t[rson]);
t[id].l = L, t[id].r = R;
}
void build(int l, int r, int id)
{
t[id].l = l, t[id].r = r;
t[id].maxx = -2e9;
if(l == r){
t[id].id = l;
t[id].maxx = sum[l];
return ;
}
else{
int mid = l + r >> 1;
build(l, mid, lson);
build(mid + 1, r, rson);
push_up(id);
}
}
Node query(int l, int r, int id)
{
int L = t[id].l, R = t[id].r;
if(L >= l && r >= R){
return t[id];
}
else{
Node ans(-2e9);
int mid = L + R >> 1;
if(mid >= l) ans = max(ans, query(l, r, lson));
if(r >= mid + 1) ans = max(ans, query(l, r, rson));
return ans;
}
}
struct Que
{
int aid, bid, val;
int l, r;
bool operator<(Que o) const{
return val < o.val;
}
Que(){}
Que(int id, int l, int r) : aid(id), l(l), r(r){
Node ans = query(l, r, 1);
bid = ans.id;
val = ans.maxx - sum[aid - 1];
}
};
signed main()
{
//IOS;
int l, r;
while(~ sdd(n, k)){
sdd(l, r);
rep(i, 1, n){
sd(a[i]);
sum[i] = sum[i - 1] + a[i];
}
build(1, n, 1);
priority_queue<Que> q;
rep(i, 1, n - l + 1){
q.push(Que(i, i + l - 1, min(i + r - 1ll, n)));
}
ll ans = 0;
rep(i, 1, k){
Que top = q.top();
q.pop();
int aid = top.aid, bid = top.bid, L = top.l, R = top.r;
ans += top.val;
if(bid != L){
q.push(Que(aid, L, bid - 1));
}
if(bid != R){
q.push(Que(aid, bid + 1, R));
}
}
pll(ans);
}
return 0;
}

浙公网安备 33010602011771号