1442AA. Extreme Subtraction(贪心思维或差分)
发布日期:2021-06-30 10:24:51 浏览次数:2 分类:技术文章

本文共 1552 字,大约阅读时间需要 5 分钟。

题意

给定一个数组,每次可以把一个前缀的数全部减一,或者把一个后缀全部减一

问最后有没有可能让所有数都变成 0 0 0


代劳们的神仙差分思路

考虑差分数组 a n s [ i ] ans[i] ans[i].如果所有数变成零,那么最后 a n s ans ans一定也是零

对于操作一,就是 a n s [ 1 ] − − , a n s [ i + 1 ] + + ans[1]- -,ans[i+1]++ ans[1],ans[i+1]++

对于操作二,就是 a n s [ i ] − − , a n s [ n + 1 ] + + ans[i]--,ans[n+1]++ ans[i],ans[n+1]++

那么观察到 a n s [ 1 ] ans[1] ans[1]只会一直减小

而后续如果想让某个 a n s [ i ] ans[i] ans[i]从负数变成零必然要用操作一

后续如果要让某个 a n s [ i ] ans[i] ans[i]从正数变成零用操作二就可以了

而且操作二不管让 a n s [ n + 1 ] ans[n+1] ans[n+1]变成多少都无所谓

因为只要保证 [ 1 , n ] [1,n] [1,n]的差分数组为零都是相同的数,那肯定能变成全是零

所以只需要关心 a n s [ 1 ] ans[1] ans[1]是不是足以让后面的所有负的 a n s [ i ] ans[i] ans[i]变成零

#include "iostream"using namespace std;const int maxn = 2e6+10;int a[maxn],n,ans[maxn];int main(){
int t; cin >> t; while( t-- ) {
cin >> n; for(int i=1;i<=n;i++) cin >> a[i], ans[i] = a[i]-a[i-1]; for(int i=2;i<=n;i++) if( ans[i]<0 ) ans[1]+=ans[i]; if( ans[1]>=0 ) cout << "YES\n"; else cout << "NO\n"; }}

我的做法贪心

宗旨是先只考虑操作一如何操作最优

只要通过操作一把序列变成不递减,说明可以只通过操作二来完成.

比如11 7 9

第一个数肯定操作了 11 11 11次,然后到第二个数,现在衰减到 7 7 7次,但是都变成了零

但是第三个数怎么办??已经不能让它等于0了

贪心策略是让它在大于等于前面数字的前提下尽量小

这个应该很好理解,大于前面的话无法通过操作二来消除

尽量小则是让操作二更容易消除

基 于 这 个 贪 心 法 则 , 甚 至 可 以 构 造 出 最 优 的 操 作 顺 序 \color{Red}基于这个贪心法则,甚至可以构造出最优的操作顺序 ,

因为这样操作最后序列变成不递减的了,可以只通过操作二来实现.

#include "iostream"using namespace std;const int maxn = 2e6+10;int a[maxn],n;int main(){
int t; cin >> t; while( t-- ) {
cin >> n; for(int i=1;i<=n;i++) cin >> a[i]; int ci = a[1], flag = 0;//初始操作次数是a[1] a[1] = 0; for(int i=2;i<=n;i++) {
if( a[i]

转载地址:https://issue-is-vegetable.blog.csdn.net/article/details/110144017 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:1442B.B. Identify the Operations(思维题。。。。)
下一篇:CF1446B. Catching Cheaters(最长上升子序列变形)

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年05月02日 20时16分36秒