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
题解
这真的是个简单题,
最少次数就是
∑max(ai−ai−1,0)
∑
m
a
x
(
a
i
−
a
i
−
1
,
0
)
怎样求出区间呢?
其实也很简单,
对于一个
ai>ai−1
a
i
>
a
i
−
1
就将i入栈相应个数,
对于一个
ai<ai−1
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;
}