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 +堆+贪心)
posted @ 2020-11-30 21:23  折翼的小鸟先生  阅读(78)  评论(0编辑  收藏  举报