您的位置:首页 > 其它

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

2014-09-06 10:44 267 查看
传送门: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  bzoj