按照最小值分治到两边,然后直接做即可。
(Theta(nlog n)) , 如果 (Theta(n)) 建笛卡尔树可以做到 (Theta(n)) .
code :
#include <bits/stdc++.h>
#define LL long long
using namespace std;
template <typename T> void read(T &x){
static char ch; x = 0,ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = x * 10 + ch - '0',ch = getchar();
}
inline void write(LL x){if (x > 9) write(x/10); putchar(x%10+'0'); }
const int N = 100005;
int n,k,a[N],Log[N],mn[N][20];
struct data{
LL ans,r;
data(){ ans = r = 0; }
inline void add(LL v){ r += v; if (r > 0) ans += ceil(r * 1.0 / k),r -= ceil(r * 1.0 / k) * k; }
};
inline int Mn(int l,int r){
static int t; t = Log[r-l+1],l = mn[l][t],r = mn[r-(1<<t)+1][t];
return a[l] < a[r] ? l : r;
}
data solve(int l,int r,int h){
if (l > r) return data();
if (l == r){ data tmp; tmp.add(a[l]-h); return tmp; }
int p = Mn(l,r); data tmp = solve(l,p-1,a[p]),R = solve(p+1,r,a[p]);
tmp.ans += R.ans,tmp.add(R.r),tmp.add((LL)(r-l+1)*(a[p]-h));
return tmp;
}
int main(){
int i,j,x,y;
read(n),read(k);
for (i = 1; i <= n; ++i) read(a[i]),mn[i][0] = i;
for (i = 1; i <= n; ++i){ Log[i] = Log[i-1]; if ((1<<Log[i]+1) < i) ++Log[i]; }
for (j = 1; j <= Log[n]; ++j) for (i = 1; i+(1<<j)-1 <= n; ++i)
x = mn[i][j-1],y = mn[i+(1<<j-1)][j-1],mn[i][j] = a[x] < a[y] ? x : y;
write(solve(1,n,0).ans),putchar('
');
return 0;
}