题目:
排列(sum.cpp/c/pas)
时间限制:1s
内存限制:256MB
【问题描述】给出一个随机的排列,请你计算最大值减最小值的差小于等于 0~n-1 的区间分别有多少个。
【输入】 TYVJ.CN输入文件名为 sum.in。第一行一个数 T(<=10),表示数据组数对于每一组数据:第一行一个数 n(1<=n<=100,000)第二行 n 个数 a1...an,表示一个随机的排列。
【输出】输出文件名为 sum.out。对于每组数据输出 n 行,分别表示差值小于等于 0~n-1 的区间个数
【输入样例】sum.in sum.out
1
4
3 2 4 1
【输出样例】
4
5
7
10
【数据说明】对于 30%的数据,1<=n<=300;对于 60%的数据,1<=n<=5000对于 100%的数据,1<=n<=100000
个人题解:(注:打开关闭文件已隐藏,而且这只是个人题解,可能过不了所有点,不过样例是过了的。)
var
t,n,i:longint;
a:array[1..100000]of longint;
{
Procedure openn;
begin
assign(input,'sum.in'); assign(output,'sum.out');
reset(input); rewrite(output);
end;
Procedure closee;
begin
close(input); close(output);
end;
}
Function maxmin(i,j:longint):longint; //此函数的目的为找到子区间中最大值和最小值,并把差值赋值给函数maxmin;
var k,max,min:longint;
begin
max:=a[i]; min:=a[i];
for k:=i to j do
begin
if a[k]>max then max:=a[k];
if a[k]<min then min:=a[k];
end;
maxmin:=max-min;
end;
Procedure pai;
var
b:array[0..100000]of longint;//记录每一个小于等于0~n-1的差值的数目。
i,j,k:longint;
begin
readln(n);
for i:=1 to n do
read(a[i]);
readln;
i:=1; j:=1;
repeat
for k:=maxmin(i,j) to n-1 do //把从子区间中最大值和最小值的差,到n-1的所有个数都加一。
inc(b[k]);
inc(j);
if j>n then begin inc(i); j:=i; end;//这两步是在列举每一个子区间。i,j相当于两个指针。
until (i>n)and(j>n);//直到区间列举完毕。
for i:=0 to n-1 do
writeln(b[i]);
end;
BEGIN //(以下不解释)
//openn;
readln(t);
for i:=1 to t do pai;
//closee;
END.