【Codeforces 1392C】 Omkar and Waterslide | 思维、差分

题目链接:https://codeforces.ml/contest/1392/problem/C

题目大意:

给出一个长度为N的序列a,每次可以选择一段连续的单调不减的区间,使得这个区间的数都+1

问最少操作几次可以使得这个序列单调不减。

题目思路:

一般的思维题

首先可以确定的是,最终序列的首相即为a[1]

因为考虑最优答案,所以不会让序列代价变得更大

所以考虑从a[1] 开始的一个连续递增子序列即为最后的序列去重之后的结果

所以说用单调栈即可维护或者什么东西都可以

然后就可以知道每个位置的最终状态要变成数是什么

这时候令f[i] = aim[i] - num[i]

对f数组进行《积木大赛》的操作即可

《积木大赛》:每次可以对一段区间操作,问操作几次可以得到结果?

Code:

/*** keep hungry and calm CoolGuang!***/
#pragma GCC optimize(3)
#include 
#define debug(x) cout<<#x<<":"<'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll num[maxn];
ll f[maxn];
int st[maxn],pre[maxn];
int b[maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        ll maxl = -INF;
        for(int i=1;i<=n;i++) read(num[i]);
        int s;st[s = 0] = 0;
        for(int i=1;i<=n;i++){
            while(s&&num[st[s]]<=num[i]) s--;
            if(!s) pre[i] = num[i];
            else pre[i] = pre[st[s]];
            st[++s] = i;
        }
        ll ans = 0;
        for(int i=1;i<=n;i++) f[i] = pre[i]-num[i];
        for(int i=1;i<=n;i++) ans += (f[i]-f[i-1])>0?(f[i]-f[i-1]):0;
        printf("%lld\n",ans);
    }
    return 0;
}
/**
4 1 2 3 5
***/

Updeta:

看到题解写法..

emmm 小题大作了hhhh

其实最终状态确定之后就是倒着的差分。

你可能感兴趣的:(思维锻炼,差分,扫描线)