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,输出可以以任意顺序输出。 
 

Solution

方法一:

用分治的思想,每次找到这个区间最小的,

然后分为左区间和右区间,重复以上操作。

方法二:

如图:n=6

若a[i]>a[i-1],就标记(a[i]-a[i-1])个+1,

若a[i]<a[i-1],就标记(a[i-1]-a[i])个-1,

对于每个+1和向右最靠近这个+1的-1匹配,即为结果。

下面代码为方法二。

 

代码

 1 var
 2   n,ans,nm:longint;
 3   a,l:array [0..100001] of longint;
 4 procedure init;
 5 var
 6   i:longint;
 7 begin
 8   readln(n);
 9   ans:=0;
10   for i:=1 to n do
11     begin
12       read(a[i]);
13       if a[i]>a[i-1] then
14         ans:=ans+a[i]-a[i-1];
15     end;
16 end;
17 
18 procedure main;
19 var
20   i,j,k:longint;
21 begin
22   nm:=0;
23   for i:=1 to n+1 do
24     begin
25       if a[i]>a[i-1] then
26         begin
27           k:=a[i]-a[i-1];
28           for j:=1 to k do
29             begin
30               inc(nm);
31               l[nm]:=i;
32             end;
33         end;
34       if a[i]<a[i-1] then
35         begin
36           k:=a[i-1]-a[i];
37           for j:=1 to k do
38             begin
39               writeln(l[nm],' ',i-1);
40               dec(nm);
41             end;
42         end;
43     end;
44 end;
45 
46 begin
47   assign(input,'range.in');
48   assign(output,'range.out');
49   reset(input);
50   rewrite(output);
51   init;
52   writeln(ans);
53   main;
54   close(input);
55   close(output);
56 end.

 

猜你喜欢

转载自www.cnblogs.com/zyx-crying/p/9477724.html
今日推荐