简要题意:
每次把一段区间 (+1),问得到 (a) 数组的最小次数。
我们可以把 (+1) 得到 (a) 换成,从 (a) 依次 (-1) 得到 (0).
算法一
每次求出最小值,然后所有数减掉它。
这样归并下去。
时间复杂度: (O(n^2)).
实际得分:(70pts).
算法二
用线段树维护最小值和区间修改。
时间复杂度:(O(n log n))
实际得分:(100pts)
算法三
你会发现,显然 (a_{i-1}) 会被减去 (a_{i-1}) 次。
此时如果 (a_{i-1} > a_i) ,则这两个数一共只需要 (a_{i-1}) 次,可以包含。
否则,就需要 (a_i) 次,也可以理解成 (a_{i-1} + (a_i - a_{i-1}))
所以,总答案为:
(sum_{i=1}^n max(a_i-a_{i-1},0))
其中 (a_0=0).
这个原理是,能扩展则扩展,否则分立为差。
时间复杂度:(O(n)).
实际得分:(100pts).
#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+1;
typedef long long ll;
inline int read(){char ch=getchar();int f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
int x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
int n,t;
ll ans=0;
int main(){
n=read(); t=0;
for(int i=1,x;i<=n;i++) {
x=read(); ans+=max(x-t,0);
t=x; // t = a_[i-1] , x = a[i]
} printf("%lld
",ans);
return 0;
}