[差分] Jzoj P5812 区间

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
 

Data Constraint

 

Hint

下发样例中第 i 个样例与第 i 组数据范围相符。
对于样例 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 }

 

posted @ 2018-08-14 16:08  BEYang_Z  阅读(376)  评论(0编辑  收藏  举报