现在的位置: 首页 > 综合 > 正文

【BZOJ】【P2006】【NOI2010】【超级钢琴】【题解】【堆+ST】

2017年04月17日 ⁄ 综合 ⁄ 共 1397字 ⁄ 字号 评论关闭

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2006

在堆里维护每个以i为左端点的区间,取出来一个区间[i,j]后,再加入[l,j-1]的max和[j+1,r]的max,l,r是指i向右可控制的范围

Code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
typedef pair<int,int> pii;
int n,k,L,R;
int a[maxn],sum[maxn];
int f[20][maxn],g[20][maxn];
long long ans=0;
void ST_init(){
	int BIT=0;
	for(int i=n;i;i>>=1,BIT++);
	for(int i=1;i<=n;i++)f[0][i]=sum[i],g[0][i]=i;
	for(int i=1;i<=BIT;i++)
	for(int j=1;j<=n-(1<<i)+1;j++){
		if(f[i-1][j]>f[i-1][j+(1<<i-1)])
			f[i][j]=f[i-1][j],g[i][j]=g[i-1][j];
		else f[i][j]=f[i-1][j+(1<<i-1)],g[i][j]=g[i-1][j+(1<<i-1)];
	}
}
pii qmax(int l,int r){
	int BIT=0;
	for(int i=r-l+1;i;i>>=1,BIT++);BIT--;
 	if(f[BIT][l]>f[BIT][r-(1<<BIT)+1])return pii(g[BIT][l],f[BIT][l]);  
    else return pii(g[BIT][r-(1<<BIT)+1],f[BIT][r-(1<<BIT)+1]);  	
}
struct zky{
	int i,j,l,r,v;
	zky(int i=0,int j=0,int l=0,int r=0,int v=0):
		i(i),j(j),l(l),r(r),v(v){}
	bool operator<(const zky &sb)const{
		return v<sb.v;
	}
};
priority_queue<zky>q;
int main(){
	scanf("%d%d%d%d",&n,&k,&L,&R);
	for(int i=1;i<=n;i++)scanf("%d",a+i),sum[i]=sum[i-1]+a[i];
	ST_init();
	for(int i=1;i<=n;i++){
		if(i-1+L>n)break;  
		pii x=qmax(i+L-1,min(i+R-1,n));
		q.push(zky(i,x.first,i-1+L,min(i+R-1,n),x.second-sum[i-1]));  
	}
	while(k--){
		zky x=q.top();q.pop();
		ans+=x.v;
		if(x.j-1>=x.l){
			pii t=qmax(x.l,x.j-1);
			q.push(zky(x.i,t.first,x.l,x.j-1,t.second-sum[x.i-1])); 
		}
		if(x.j+1<=x.r){
	        pii t=qmax(x.j+1,x.r);  
            q.push(zky(x.i,t.first,x.j+1,x.r,t.second-sum[x.i-1]));  		
		}
	}cout<<ans<<endl;
	return 0;
}

抱歉!评论已关闭.