# ST表

### (此处log需要下取整)

void prepare()
{
lg[0]=-1;
for(re int i=1;i<=n;++i) lg[i]=lg[i/2]+1;
for(re int i=1;i<=lg[n];++i)
for(re int j=1;j<=n;++j)
f[j][i]=MAX(f[j][i-1], f[j+(1<<i-1)][i-1]);
}
int query(int l,int r)
{
int LOG=lg[r-l+1];
return MAX(f[l][LOG],f[r-(1<<LOG)+1][LOG]);
}



n,m<=500000

## code

#include<bits/stdc++.h>
using namespace std;
#define re register
#define in inline
#define get getchar()
#define ll long long
{
int t=0, x=1; char ch=get;
while(ch!='-' && (ch<'0' || ch>'9') ) ch=get;
if(ch=='-') ch=get, x=-1;
while(ch<='9' && ch>='0') t=t*10+ch-'0', ch=get;
return t*x;
}
const int _=1e6+23;
const int LG=22;
int f[_][LG],n,k,L,R,a[_],lg[_];
in int MAX(int x,int y){ return a[x]>a[y] ? x : y;}
in int query(int l,int r)
{
int LOG=lg[r-l+1];
return MAX(f[l][LOG],f[r-(1<<LOG)+1][LOG]);
}
struct yzx{
int l,r,num;
int val(){ return a[query(l,r)] - a[num-1];}
}; //表示每个可能最大值区间右端点范围[l,r],以及左端点编号num
yzx YZX(int a,int b,int c){return yzx{a,b,c}; }
bool operator < (yzx x,yzx y){ return x.val() < y.val(); }
priority_queue<yzx> q;
int main()
{
lg[0]=-1;
for(re int i=1;i<=n;++i) a[i]=read()+a[i-1], f[i][0]=i, lg[i]=lg[i/2]+1;
for(re int i=1;i<=lg[n];++i)
for(re int j=1;j<=n;++j)
f[j][i]=MAX(f[j][i-1], f[j+(1<<i-1)][i-1]);
for(re int i=1;i<=n;++i) {
int st=i+L-1;
if(st>n) break;
q.push(YZX(st,min(n,st+(R-L)),i));
}
ll ans=0;
while(k--)
{
yzx u=q.top(); q.pop();
ans+=u.val();
int pos=query(u.l,u.r);
if(pos>u.l) q.push(YZX(u.l,pos-1,u.num));
if(pos<u.r) q.push(YZX(pos+1,u.r,u.num));
}
cout<<ans<<endl;
return 0;
}


posted @ 2021-05-18 22:16  yzhx  阅读(48)  评论(0编辑  收藏  举报