[POJ3928 Ping pong]

[题目来源]:Beijing 2008

[关键字]:树状数组

[题目大意]:是要组成许多比赛,比赛的要求是,两个人比赛一个人作裁判,裁判的能力值必须要在两个人之间,位置也是,问一共有多少种不同的比赛方式。每个人的能力值各不相同。

//=====================================================================================================

[分析]:枚举一个中间点,查找它左边有几个比它能力值小的右边有几个比它能力值大的,根据乘法原理将其相乘;再查找它左边有几个比它能力值大的右边有几个比它能力值小的,根据乘法原理将其相乘。把每个点相加就是最终结果(int64)。剩下的问题就是如何求左右需要的值。先将其从小到大进行排序,然后按原来顺序枚举中间点,计算完后就将其插入它在排序后的位置上。所以统计时就是利用树状数组统计从1到枚举的中间点在排序后的位置之间有多少数,就是左边比它小的,用此时树状数组中的所有值(就是前i个数)的减去左边它小得和就是左边比它大的,再n到1来一遍就求出右边,再相乘。

[代码]:

View Code
  1 program Project1;
2 type
3 rec = record
4 x, p: longint;
5 end;
6 var
7 n, tt: longint;
8 a: array[0..20010] of rec;
9 fmin, fmax, bmin, bmax, b, tree: array[0..20010] of longint;
10
11 procedure qs(l, r: longint);
12 var
13 i, j, mid: longint;
14 t: rec;
15 begin
16 i := l;
17 j := r;
18 mid := a[(l+r) shr 1].x;
19 repeat
20 while a[i].x < mid do inc(i);
21 while a[j].x > mid do dec(j);
22 if i <= j then
23 begin
24 t := a[i];
25 a[i] := a[j];
26 a[j] := t;
27 inc(i);
28 dec(j);
29 end;
30 until i > j;
31 if l < j then qs(l,j);
32 if i < r then qs(i,r);
33 end;
34
35 procedure init;
36 var
37 i: longint;
38 begin
39 read(n);
40 for i := 1 to n do
41 begin
42 read(a[i].x);
43 a[i].p := i;
44 end;
45 qs(1,n);
46 for i := 1 to n do b[a[i].p] := i;
47 end;
48
49 function lowbit(k: longint):longint;
50 begin
51 lowbit := k and -k;
52 end;
53
54 function find(k: longint):longint;
55 var
56 sum: longint;
57 begin
58 sum := 0;
59 while k >= 1 do
60 begin
61 sum := sum+tree[k];
62 k := k-lowbit(k);
63 end;
64 exit(sum);
65 end;
66
67 procedure ins(k: longint);
68 begin
69 while k <= n do
70 begin
71 tree[k] := tree[k]+1;
72 k := k+lowbit(k);
73 end;
74 end;
75
76 procedure work;
77 var
78 i, temp: longint;
79 ans: int64;
80 begin
81 fillchar(tree,sizeof(tree),0);
82 for i := 1 to n do
83 begin
84 temp := find(b[i]);
85 fmin[i] := temp;
86 fmax[i] := find(n)-temp;
87 ins(b[i]);
88 end;
89 fillchar(tree,sizeof(tree),0);
90 for i := n downto 1 do
91 begin
92 temp := find(b[i]);
93 bmin[i] := temp;
94 bmax[i] := find(n)-temp;
95 ins(b[i]);
96 end;
97 //for i := 1 to n do writeln(fmin[i],'',fmax[i]);
98 ans := 0;
99 for i := 1 to n do
100 ans := ans+(fmin[i]*bmax[i])+(fmax[i]*bmin[i]);
101 writeln(ans);
102 //readln;
103 //readln;
104 end;
105
106 begin
107 read(tt);
108 while tt <> 0 do
109 begin
110 init;
111 work;
112 dec(tt);
113 end;
114 end.



你可能感兴趣的:(ping)