p2048 [NOI2010]超级钢琴
分析
https://www.luogu.org/blog/TheDawn/solution-p2048
和我思路差不多
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int LOG = 19;
const int inf = 1e9+7;
int pre[525000],MIN[525000][21],be[525000],wh[525000][21];
priority_queue<pair<pair<int,int>,pair<int,int> > >q;
inline int gm(int le,int ri){
if(le>ri)return inf;
int k=be[ri-le+1];
return min(MIN[le][k],MIN[ri-(1<<k)+1][k]);
}
inline int gwhm(int le,int ri){
int k=be[ri-le+1];
return MIN[le][k]<MIN[ri-(1<<k)+1][k]?wh[le][k]:wh[ri-(1<<k)+1][k];
}
inline int ra(){
int x=0,f=1;char s=getchar();
while(!isdigit(s)){if(s=='-')f=-1;s=getchar();}
while(isdigit(s))x=(x<<3)+(x<<1)+(s-'0'),s=getchar();
return x*f;
}
int main(){
int n,m,i,j,k,L,R;
long long Ans=0;
n=ra(),k=ra(),L=ra(),R=ra();
for(i=1;i<=n;++i){
int x;
x=ra();
pre[i]=pre[i-1]+x;
MIN[i][0]=pre[i];
wh[i][0]=i;
}
for(i=1;i<=LOG;++i)
for(j=(1<<(i-1));j<(1<<i);++j)
be[j]=i-1;
for(i=0;i<LOG;++i)
for(j=0;(1<<(i+1))+j-1<=n;++j){
MIN[j][i+1]=min(MIN[j][i],MIN[j+(1<<i)][i]);
if(MIN[j][i+1]==MIN[j][i])wh[j][i+1]=wh[j][i];
else wh[j][i+1]=wh[j+(1<<i)][i];
}
for(i=1;i<=n;++i)
q.push(make_pair(make_pair(pre[i]-gm(max(0,i-R),i-L),i),
make_pair(max(1,i-R+1),i-L+1)));
while(k){
int x=q.top().first.second;
int le=q.top().second.first,ri=q.top().second.second;
int pl=gwhm(le-1,ri-1)+1;
Ans+=1ll*q.top().first.first,--k;
q.pop();
if(le<pl)
q.push(make_pair(make_pair(pre[x]-gm(le-1,pl-2),x),make_pair(le,pl-1)));
if(pl<ri)
q.push(make_pair(make_pair(pre[x]-gm(pl,ri-1),x),make_pair(pl+1,ri)));
}
cout<<Ans;
return 0;
}