【BZOJ-2006】超级钢琴 ST表 + 堆 （一类经典问题）

2006: [NOI2010]超级钢琴

Time Limit: 20 Sec  Memory Limit: 552 MB
Submit: 2473  Solved: 1211
[Submit][Status][Discuss]

4 3 2 3
3
2
-6
8

11

【样例说明】

HINT

N<=500,000
k<=500,000
-1000<=Ai<=1000,1<=L<=R<=N且保证一定存在满足条件的乐曲

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 500010
int N,K,L,R,A[MAXN],SA[MAXN];
long long ans;
struct HeapNode
{
int i,L,R,val,pos;
bool operator < (const HeapNode & A) const
{return val<A.val;}
};
inline int Max(int x,int y) {return SA[x]>SA[y]? x:y;}
int log2[MAXN],dp[20][MAXN];
void ST()
{
log2[0]=-1;
for (int i=1; i<=N; i++)
if (i&(i-1)) log2[i]=log2[i-1]; else log2[i]=log2[i-1]+1;
for (int i=1; i<=N; i++) dp[0][i]=i;
for (int j=1; (1<<j)<=N; j++)
for (int i=1; i+(1<<j)-1<=N; i++)
dp[j][i]=Max(dp[j-1][i],dp[j-1][i+(1<<j-1)]);
}
inline int RMQ(int l,int r)
{
int tmp=log2[r-l+1];
return Max(dp[tmp][l],dp[tmp][r-(1<<tmp)+1]);
}
priority_queue<HeapNode>heap;
int main()
{
for (int i=1; i<=N; i++) A[i]=read(),SA[i]=SA[i-1]+A[i];
ST();
for (int i=1; i<=N; i++)
if (i+L-1<=N)
{
int ls=i+L-1,rs=min(i+R-1,N),pos=RMQ(ls,rs),val=SA[pos]-SA[i-1];
heap.push( (HeapNode){i,ls,rs,val,pos} );
}
else break;
while (!heap.empty() && K)
{
HeapNode now=heap.top(); heap.pop();
ans+=now.val; K--;
HeapNode ls=now,rs=now;
ls.R=now.pos-1;
if (ls.R>=ls.L)
ls.pos=RMQ(ls.L,ls.R),ls.val=SA[ls.pos]-SA[ls.i-1],heap.push(ls);
rs.L=now.pos+1;
if (rs.R>=rs.L)
rs.pos=RMQ(rs.L,rs.R),rs.val=SA[rs.pos]-SA[rs.i-1],heap.push(rs);
}
printf("%lld\n",ans);
return 0;
}

posted @ 2016-08-18 14:44  DaD3zZ  阅读(647)  评论(0编辑  收藏  举报