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