JZOJ5812. 【NOIP提高A组模拟2018.8.14】 区间

Description

每一个机房中总有一个红太阳。有一天,AmberFrame 来到机房,发现桌上有不知道哪个蒟蒻放上的问 题: 有一个 n 个数的序列,一开始所有的数都是 0,每次可以将一个区间 [l, r](l ≤ r) 内的数 +1,求到达最 终状态的最少操作次数。 AmberFrame 非常强,自然不会把时间花在这种水题上。因此他就把任务交给了你,如果不会做的话,他 可能就会觉得你就是那个放问题的蒟蒻了而把你批判一番了。

Input

第一行包含一个正整数 n,表示序列的长度。
第二行包含 n 个非负整数 a1, a2, …, an,表示最终的状态。

Output

输出的第一行是一个正整数 m,表示最少的操作次数。 接下来 m 行每行两个正整数 li , ri,表示一次操作。你需要保证 1 ≤ li ≤ ri ≤ n。 保证最少次数 m ≤ 10^5,输出可以以任意顺序输出。

Sample Input

6
2 3 3 3 3 3

Sample Output

3
1 6
1 6
2 6

题解

这真的是个简单题,
最少次数就是
m a x ( a i a i 1 , 0 )
怎样求出区间呢?
其实也很简单,
对于一个 a i > a i 1 就将i入栈相应个数,
对于一个 a i < a i 1 就将相应个数的数出栈,作为左端点,这个位置的前一个作为右端点。

code

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string.h>
#include <cmath>
#include <math.h>
#define ll long long
#define N 100003
#define M 103
#define db double
#define P putchar
#define G getchar
using namespace std;
char ch;
void read(int &n)
{
    n=0;
    ch=G();
    while((ch<'0' || ch>'9') && ch!='-')ch=G();
    ll w=1;
    if(ch=='-')w=-1,ch=G();
    while('0'<=ch && ch<='9')n=(n<<3)+(n<<1)+ch-'0',ch=G();
    n*=w;
}

int max(int a,int b){return a>b?a:b;}
int min(int a,int b){return a<b?a:b;}
void write(ll x){if(x>9) write(x/10);P(x%10+'0');}

int n,ans,a[N],z[N],top;

int main()
{
    freopen("range.in","r",stdin);
    freopen("range.out","w",stdout);

    read(n);
    for(int i=1;i<=n;i++)
        read(a[i]),ans=ans+max(a[i]-a[i-1],0);
    printf("%d\n",ans);
    for(int i=1;i<=n;i++)
        if(a[i]>a[i-1])
        {
            for(int j=a[i-1];j<a[i];j++)
                z[++top]=i;
        }
        else
        {
            for(int j=a[i];j<a[i-1];j++)
                write(z[top--]),P(' '),write(i-1),P('\n');
        }
    for(;top;top--)
        write(z[top]),P(' '),write(n),P('\n');

    return 0;
}

猜你喜欢

转载自blog.csdn.net/lijf2001/article/details/81673608
今日推荐