P1969 积木大赛 题解

博客园同步

原题链接

简要题意:

每次把一段区间 + 1 +1 ,问得到 a a 数组的最小次数。

我们可以把 + 1 +1 得到 a a 换成,从 a a 依次 1 -1 得到 0 0 .

算法一

每次求出最小值,然后所有数减掉它。

这样归并下去。

时间复杂度: O ( n 2 ) O(n^2) .

实际得分: 70 p t s 70pts .

算法二

用线段树维护最小值和区间修改。

时间复杂度: O ( n log n ) O(n \log n)

实际得分: 100 p t s 100pts

算法三

你会发现,显然 a i 1 a_{i-1} 会被减去 a i 1 a_{i-1} 次。

此时如果 a i 1 > a i a_{i-1} > a_i ,则这两个数一共只需要 a i 1 a_{i-1} 次,可以包含。

否则,就需要 a i a_i 次,也可以理解成 a i 1 + ( a i a i 1 ) a_{i-1} + (a_i - a_{i-1})

所以,总答案为:

i = 1 n max ( a i a i 1 , 0 ) \sum_{i=1}^n \max(a_i-a_{i-1},0)

其中 a 0 = 0 a_0=0 .

这个原理是,能扩展则扩展,否则分立为差。

时间复杂度: O ( n ) O(n) .

实际得分: 100 p t s 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\n",ans);
	return 0;
}

发布了31 篇原创文章 · 获赞 37 · 访问量 589

猜你喜欢

转载自blog.csdn.net/bifanwen/article/details/105289381
今日推荐