【OJ2618】区间

2618 -- 区间(Solution)

题目 : 有一个 \(n\) 个数的序列,一开始所有的数都是 \(0\) ,每次可以将一个区间 $[l,r],(l ≤ r) $内的数 \(+1\) ,求到达最终状态的最少操作次数。

Tag: 模拟、差分

Analysis By LC:

考虑差分的过程,一次操作就等同于 \(s[l]++\, ,s[r+1]--\) 。每个数便是差分数组的前缀和。那么我们可以尝试还原出差分数组:我们将每个数减去前面的那个数,就得到了一个目标序列的差分序列,考虑通过差分数组序列出操作:如果还原后的数组 \(a[i]>0\) ,那么 \(i\) 一定是起点,并且作为 \(a[i]\) 次起点;反之,如果 \(a[i]<0\) ,那么 \(i\) 一定作为 \(-a[i]\) 次终点。接下来就对应输出即可。

Code By LC :

#include<cstdio>
const int N=100005;
int a[N],op[N],ed[N],ans1[N],ans2[N],id,m;
inline int _read()
{
    char c; int x=0;
    for(;c<'0'||c>'9';c=getchar());
    for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+c-'0';
    return x;
}
int main()
{
    int n=_read();
    for(int i=1;i<=n;i++) a[i]=_read();
    for(int i=0;i<=n+1;i++)
    {
        if(a[i]>a[i-1]) op[i]+=a[i]-a[i-1];
        if(a[i]>a[i+1]) ed[i]+=a[i]-a[i+1];
    }
    int i=1,j=1;
    while(true)
    {
        while(i<=n&&!op[i]) ++i;
        while(j<=n&&!ed[j]) ++j;
        if(j>n) break;
        m++; ans1[m]=i,ans2[m]=j;
        --op[i]; --ed[j];
    }
    printf("%d\n",m);
    for(int i=1;i<=m;i++) printf("%d %d\n",ans1[i],ans2[i]);
}

猜你喜欢

转载自www.cnblogs.com/farway17/p/9347179.html
OJ