P2048 [NOI2010]超级钢琴 (rmq +堆+贪心)
题目链接
一道练习st表的好题,特此记录一下,具体思路题解写的很清晰,这就不
写了(其实想写但太懒了)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<algorithm>
#include<cmath>
#define int long long
using namespace std;
const int maxn=5e5+10;
inline int read(){
int ret=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')
f=-f;
ch=getchar();
}
while(ch<='9'&&ch>='0'){
ret=ret*10+(ch^'0');
ch=getchar();
}
return ret*f;
}
int n,k,l,r;
int a[maxn];
int sum[maxn];
int f[maxn][30];
void pre(int n){
for(int i=1;i<=n;i++){
f[i][0]=i;
}
for(int j=1;(1<<j)<=n;j++){
for(int i=1;i+(1<<j)-1<=n;i++){
int x=f[i][j-1];
int y=f[i+(1<<j-1)][j-1];
if(sum[x]>sum[y]){
f[i][j]=x;
}
else
f[i][j]=y;
//cout<<
}
}
}
int query(int l,int r){
int len=log2(r-l+1);
int x=f[l][len];
int y=f[r-(1<<len)+1][len];
if(sum[x]>sum[y]){
return x;
}
else {
return y;
}
}
struct hp{
int po,l,r,t;
hp(){}
hp(int po,int l,int r):po(po),l(l),r(r),t(query(l,r)){};
};
bool operator < (const hp &x,const hp &y){
return sum[x.t]-sum[x.po-1]<sum[y.t]-sum[y.po-1];
}
priority_queue<hp>q;
int min(int x,int y){
if(x>y){
return y;
}
else
return x;
}
signed main(){
freopen("a.in","r",stdin);
n=read();
k=read();
l=read();
r=read();
for(int i=1;i<=n;i++){
sum[i]+=sum[i-1]+read();
}
pre(n);
for(int i=1;i<=n;i++){
if(i+l-1<=n){
q.push(hp(i,l+i-1,min(i+r-1,n)));
}
}
int ans=0;
for(int i=1;i<=k;i++){
int po=q.top().po;
int ll=q.top().l;
int rr=q.top().r;
int t=q.top().t;
q.pop();
ans+=sum[t]-sum[po-1];
if(t>l)
q.push(hp(po,ll,t-1));
if(t<r)
q.push(hp(po,t+1,rr));
}
cout<<ans;
return 0;
}
```P2048 [NOI2010]超级钢琴 (rmq +堆+贪心)