JZOJ 5812. 【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
 

Data Constraint

 

Hint

下发样例中第 i 个样例与第 i 组数据范围相符。
对于样例 1,第一个数被加了两次,其他每个数都被加了三次,显然满足条件。
 
做法:一开始还想用线段树来着,后来发现会超时,题解上说打差分从头到尾扫一遍就好啦
 
代码如下:
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 100007
 5 using namespace std;
 6 int n, a[N], list[N], tot, ans;
 7 
 8 int abs (int x) { return x > 0 ? x : -x; }
 9 
10 void Work(int step, int Times)
11 {
12     for (; Times--; list[++tot] = step);
13 }
14 
15 void Print(int step, int Times)
16 {
17     for(; Times--; printf("%d %d\n", list[tot--], step));
18 }
19 
20 int main()
21 {
22     freopen("range.in", "r", stdin);
23     freopen("range.out", "w", stdout);
24     scanf("%d", &n);
25     for (int i = 1; i <= n; scanf("%d", &a[i++]));
26     for (int i = 1; i <= n; i++)
27         if (a[i] > a[i - 1])    ans += a[i] - a[i - 1];
28     printf("%d\n", ans);
29     for (int i = 1; i <= n + 1; i++)
30     {
31         if (a[i] > a[i - 1])     Work(i, abs(a[i] - a[i - 1]));
32         if (a[i] < a[i - 1])    Print(i - 1, abs(a[i] - a[i - 1]));
33     }
34 }
View Code

猜你喜欢

转载自www.cnblogs.com/traveller-ly/p/9479252.html