Codeforces Round #812 (Div. 2) B Optimal Reduction

发布于:2022-08-07 ⋅ 阅读:(356) ⋅ 点赞:(0)

Problem - B - Codeforces

题意:

有一种操作:你可以选定一个区间,并把这个区间中所有的数都减1

给你一个数列a,数列a会有多种排列,问你当前给你的这种排列是不是这么多种排列中把所有的元素都变为0的最少操作数的排列

思路:

看到题,第一件事就是判断这属于什么题,这是贪心+操作

对于操作题,我们先直观想象一下该操作

然后我们去样例观察该操作具有一些什么性质,或者手写模拟一下

在观察操作有什么性质时,我们关注的是和问题有关的性质

我们关注的是操作次数,当区间[l,r]中间存在0元素时,就不能在这个区间内整体操作了,就只能分成两段区间操作了

当区间中间不会先比两边先出现0时,我们把操作区间慢慢往中间移动,这样操作次数就是\underset{l<=i<=r}{max}a[i]

但是如果中间先出现0时,操作次数就是\underset{l<=i<=m-1}{max}a[i]+\underset{m+1<=i<=r}{max}a[i]

因为中间那个先变为0的元素不会是\underset{l<=i<=r}{max}a[i]

所以

\underset{l<=i<=m-1}{max}a[i]+\underset{m+1<=i<=r}{max}a[i]>=\underset{l<=i<=r}{max}a[i]

因此当区间中间先变为0,贡献只会增加不会减少(贪心的思想

因此这个就是操作的性质

因此不能让中间先变成0

所以中间应该比两边大,即这应该是一个单峰函数

Code:

void solve(){
    int n,ok=1,flag=1;
    int a[mxn];
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n-1;i++){
        if(a[i]>a[i+1]) flag=0;
        if(!flag&&a[i]<a[i+1]) ok=0; 
    }
    if(!ok) puts("NO");
    else puts("YES");
}

总结:

看到题,先判断这是什么题,再去确定思考方向,否则思路太乱了

对于操作题,我们

1.先直观想象一下该操作

2.然后我们去样例观察该操作具有一些什么性质,或者手写模拟一下

3.在观察操作有什么性质时,我们关注的是和问题有关的性质

当然要是想不出来看样例猜也是一种好办法,比如这道就能猜出来!

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到