第一行输入一个正整数,代表数组的元素数量。
第二行输入个正整数,代表数组的元素。
一个整数,代表最小的操作次数。
3 3 2 4
2
一种合法的操作如下:
第一次选择区间[2,2],数组变成[3,3,4]。第二次选择区间[2,3],数组变成[3,4,5],满足要求。请注意,这里的区间指选了第几个数。例如区间[2,2]代表选了第二个数,区间[2,3]代表选了第二个和第三个数。
#include <iostream> using namespace std; /** * 首先第一个点肯定不提升 * 1、考虑第二个点怎么提升:假设对于第二个点的一个提升区间是[2,k],那不如直接提升 * 区间[2,n]。因为反正要把k+1往后的都提升得比k高,既然k都提升了,则把后 * 面的一同提升也没有坏处,证明是: * (假设最优提升策略的某个提升区间是[2,k],我们把该区间改为[2,n],其它 * 提升区间不变,则结果数组的[k+1,n]部分都升高了同一个值,仍然是严格递 * 增的,因此也是一个最优提升策略)。 * 类似地,往后每个点开始的提升区间,都不妨直接延伸到n。 * 所以可以认为任何一个提升区间都是[t,n]的形式,并且多个相同的[t,n]可以合并为一个。 * * 2、提升[t,n],对于区间[t,n]的点的相对高度没有影响, * 因此区间[t+1,n]要提升的高度, * 1)如果arr[t+1]<=arr[t]的话,其实就是arr[t+1]-arr[t]+1。 * 2)否则就不用专门提升该区间。 */ int main() { int n; long count = 0; cin>>n; long prev,tmp; cin>>prev; for(int i=1;i<n;i++){ cin>>tmp; if(prev>=tmp) count+=prev-tmp+1; prev=tmp; } cout<<count; } // 64 位输出请用 printf("%lld")
package main import "fmt" var total = 0 //总操作数 func main() { var num int fmt.Scan(&num) a := make([]int, num) for i := 0; i < num; i++ { fmt.Scan(&a[i]) } // 倒置 for i := 0; i < num/2; i++ { a[i], a[num-i-1] = a[num-i-1], a[i] } fmt.Println(a) for i := 1; i < num; i++ { if a[i] >= a[i-1] { // 新加入的a[i]不会受到a[i-1]的影响,下次计算保持原值,就很方便 total += a[i] - a[i-1] + 1 } } fmt.Println(total) }
#include <iostream> #include <vector> using namespace std; int main() { int n; cin >> n; vector<int> v(n, 0); for (auto&e: v) cin >> e; int i = 0; int64_t ret = 0; while (i < v.size()-1) { if (v[i] >= v[i+1]) ret += v[i] - v[i+1] + 1; i++; } std::cout<<ret<<std::endl; } // 64 位输出请用 printf("%lld")
# 贪心:区间严格递增的最少操作次数 # 4 2 9 19 2 -->将后面的数都递增:4 5 12 22 5 等价于只递增一个数:4 5 9 19 2 # 因为他们的差值不变 # 只需要找到第一个开始减小的位置,然后计算差值 n = int(input()) line1 = input() num = list(map(int, line1.split())) count = 0 dif = 0 for i in range(1,len(num)): if num[i] <= num[i-1]: dif = num[i-1] - num[i] + 1 count += dif print(count)