# [NOI2010]: Super piano

Portal
This question is interesting...
Smart use of st table and heap
First of all, I won't talk about the most violent
The second violence is the chairman tree + heap, with an expected score of 70-80 and time O(klog2n)
std is to store the possible interval with heap, and then query the minimum value of interval with st table
Because in fact, if you know the right end of the interval, you need to deal with prefixes and s
So as long as the minimum value of query interval is enough, you can do it in st table O(1)
code:

```#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#define mp(a,b,c,d) make_pair(make_pair(a,b),make_pair(c,d))
#define min(a,b) s[a]>s[b]?b:a
using namespace std;
int x=0,f=1;char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
typedef pair<int,int> pii;
const int N=5e5+5;
int n,k,L,R;
int a[N],mn[19][N],Log[N],s[N];
long long ans=0;
priority_queue<pair<pii,pii> > q;
inline int query(int l,int r){
if(l>r)return -1;
int k=Log[r-l+1];
return min(mn[k][l],mn[k][r-(1<<k)+1]);
}
int main(){
for(int k=1;k<=Log[n];++k)for(int i=0;i+(1<<k)-1<=n;++i)mn[k][i]=min(mn[k-1][i],mn[k-1][i+(1<<(k-1))]);
for(int i=L;i<=n;++i)q.push(mp(s[i]-s[query(max(0,i-R),i-L)],i,max(0,i-R),i-L));
int x,a,b,c,d,y;
for(int i=1;i<=k;++i){
pii p1=q.top().first,p2=q.top().second;
ans+=p1.first;x=p1.second;a=p2.first;b=p2.second;y=query(a,b);q.pop();
c=query(a,y-1);d=query(y+1,b);
if(c!=-1)q.push(mp(s[x]-s[c],x,a,y-1));
if(d!=-1)q.push(mp(s[x]-s[d],x,y+1,b));
}
printf("%lld",ans);
return 0;
}```

Posted on Sat, 30 May 2020 10:52:52 -0400 by vahidi