Description
每一个机房中总有一个红太阳。有一天,AmberFrame 来到机房,发现桌上有不知道哪个蒟蒻放上的问 题: 有一个 n 个数的序列,一开始所有的数都是 0,每次可以将一个区间 [l, r](l ≤ r) 内的数 +1,求到达最 终状态的最少操作次数。 AmberFrame 非常强,自然不会把时间花在这种水题上。因此他就把任务交给了你,如果不会做的话,他 可能就会觉得你就是那个放问题的蒟蒻了而把你批判一番了。
Input
第一行包含一个正整数 n,表示序列的长度。
第二行包含 n 个非负整数 a1, a2, ..., an,表示最终的状态。
第二行包含 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
Data Constraint
Hint
下发样例中第 i 个样例与第 i 组数据范围相符。
对于样例 1,第一个数被加了两次,其他每个数都被加了三次,显然满足条件。
对于样例 1,第一个数被加了两次,其他每个数都被加了三次,显然满足条件。
题解
- 定义一个k,表示当前i的值
- 那么每次比较a[i]与k
- 如果a[i]>k,则打入a[i]-k个+1标记
- 如果a[i]<k,则打入k-a[i]个-1标记,并且与+1标志匹配
代码
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<algorithm> 5 using namespace std; 6 int n,ans,z; 7 int a[100005],l[100005],r[100005]; 8 int main() 9 { 10 freopen("range.in","r",stdin); 11 freopen("range.out","w",stdout); 12 scanf("%d",&n); 13 for(int i=1;i<=n;i++) scanf("%d",&a[i]); 14 int k=0; 15 for(int i=1;i<=n+1;i++) 16 { 17 while(a[i]>k) k++,l[++ans]=i; 18 while(a[i]<k) k--,r[++z]=i-1; 19 } 20 printf("%d\n",ans); 21 for(int i=1;i<=ans;i++) printf("%d %d\n",l[i],r[i]); 22 return 0; 23 }