【题解】P2048 [NOI2010]超级钢琴
【题解】[P2048 NOI2010]超级钢琴
一道非常套路的题目。是堆的套路题。
考虑前缀和,我们要是确定了左端点,就只需要在右端区间查询最大的那个加进来就好了。\(sum_j-sum_{i-1}\)嘛,我们预处理对于\(sum\)的\(st\)表,然后枚举\(i\),然后记五元组\(sum,i,l,pos,r\)分别表示这个五元组的\(sum_{pos}-sum_{i-1}\)贡献,左端点\(i\),右边范围\(l,r\),和上次使用的下标\(pos\) 。
先把所有的\((sum,i,i+L-1,maxpos,i+R-1)\)压入大根堆,按照\(sum\)排序
取出队头后,将五元组拆为\((sum',i,i+L-1,maxpos',maxpos-1)\)和\((sum'',i,maxpos+1,maxpos'',i+R-1)\)再放入堆里。
上面五元组的拆分只是意会,在代码中有些小细节不一样,不一定是\(i+L-1\),\(i+R-1\)
这样连续操作\(k\)次,他们的和就是我们要的答案。
#include<bits/stdc++.h>
using namespace std;typedef long long ll;
#define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)
#define RP(t,a,b) for(register int t=(a),edd=(b);t<=edd;++t)
#define ERP(t,a) for(register int t=head[a];t;t=e[t].nx)
#define midd register int mid=(l+r)>>1
#define TMP template < class ccf >
TMP inline ccf qr(ccf b){
register char c=getchar();register int q=1;register ccf x=0;
while(c<48||c>57)q=c==45?-1:q,c=getchar();
while(c>=48&&c<=57)x=x*10+c-48,c=getchar();
return q==-1?-x:x;}
TMP inline ccf Max(ccf a,ccf b){return a<b?b:a;}
TMP inline ccf Min(ccf a,ccf b){return a<b?a:b;}
TMP inline ccf Max(ccf a,ccf b,ccf c){return Max(a,Max(b,c));}
TMP inline ccf Min(ccf a,ccf b,ccf c){return Min(a,Min(b,c));}
TMP inline void READ(ccf* _arr,int _n){RP(t,1,_n)_arr[t]=qr((ccf)1)+_arr[t-1];}
TMP inline void Swap(ccf a,ccf b){ccf c;c=b;b=a;a=c;}
//----------------------template&IO---------------------------
#define int long long
const int maxn=500005;
int data[maxn];
int lg[maxn];
struct ST{
int sum,id;
inline bool operator <(ST a)const{return sum==a.sum?id<a.id:sum<a.sum;}
}st[maxn][32];
int n,lb,rb,k;
inline int qint(int l,int r){return Max(st[l][lg[r-l+1]],st[r-(1<<lg[r-l+1])+1][lg[r-l+1]]).sum;}
inline int qpos(int l,int r){return Max(st[l][lg[r-l+1]],st[r-(1<<lg[r-l+1])+1][lg[r-l+1]]).id ;}
struct node{
int sum,i,L,pos,R;
inline bool operator < (node a)const{return sum==a.sum?pos<a.pos:sum<a.sum;}
};
priority_queue < node > q;
inline node mk(int sum,int i,int L,int pos,int R){node ret=(node){sum,i,L,pos,R};return ret;}
signed main(){
#ifndef ONLINE_JUDGE
freopen("sequence1.in","r",stdin);
freopen("sequence.out","w",stdout);
#endif
n=qr(1);k=qr(1);lb=qr(1);rb=qr(1);
READ(data,n);
const int* sum=data;
RP(t,1,n+1){
lg[t]=lg[t-1];
if((1<<lg[t]<<1)==t)lg[t]++;
}
int ans=0;
int L=lb,R=rb;
RP(t,1,n) st[t][0].sum=data[t],st[t][0].id=t;
DRP(t,n,1){
st[t][0].sum=data[t];st[t][0].id=t;
RP(i,1,lg[n-t+1]) st[t][i]=Max(st[t][i-1],st[t+(1<<(i-1))][i-1]);
}
RP(t,1,n){
if(t+R-1<=n) q.push(mk(qint(t+L-1,t+R-1)-sum[t-1],t,t+L-1,qpos(t+L-1,t+R-1),t+R-1));
else if(t+L-1<=n) q.push(mk(qint(t+L-1,n) -sum[t-1],t,t+L-1,qpos(t+L-1,n) ,n ));
}
RP(qaqqqq,1,k){
register node now=q.top();q.pop();
ans+=now.sum;
if(now.pos>now.L&&now.pos<=now.R) q.push(mk(qint(now.L,now.pos-1)-sum[now.i-1],now.i,now.L,qpos(now.L,now.pos-1),now.pos-1));
if(now.pos<now.R&&now.pos>=now.L) q.push(mk(qint(now.pos+1,now.R)-sum[now.i-1],now.i,now.pos+1,qpos(now.pos+1,now.R),now.R));
}
cout<<ans<<endl;
return 0;
}
博客保留所有权利,谢绝学步园、码迷等不在文首明显处显著标明转载来源的任何个人或组织进行转载!其他文明转载授权且欢迎!