POJ 2299
POJ 2299 Ultra-QuickSort
(开头愤怒一句:你妹的下次记得估值范围啊,int64啊!!!)
题目大意:给出一个序列,问用冒泡排序要交换多少次才能使之变成升序?
解法:首先分析题目性质,将之转化为求一个数左侧有多少个数小于它,亦转化为一个逆序对的问题。
因为本题n最大去到50w,所以n^2是万万不能的,所以这里用到一个树状数组求逆序对的问题(也可以用归并排序的做法做)。
而这里有一个重点:离散化,注意将值一样大的数视为一样大。然后快排,同时记录他的初始位置,然后用数据a(下标同初始位置)记录大小。
树状数组做法:从最后一个开始,up(a[i], 1);然后ans := ans + getsum(a[i]-1){sum(1, a[i]-1)}因为是从后往前推,所以我只要知道右侧有多少个小于a[i]的数已出现便可直接找到。
{a[i]表示有多少个是小于I 的,跟线段覆盖有点像?}
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 const
2 maxn=500000;
3 var
4 ans, n: longint;
5 tree, a, d, p: array[1..maxn+10]of longint;
6 procedure qsort(b, e: longint);
7 var
8 i, j, k, x: longint;
9 begin
10 i := b;
11 j := e;
12 x := d[(i+j)shr 1];
13 repeat
14 while d[i]<x do inc(i);
15 while d[j]>x do dec(j);
16 if i<=j then
17 begin
18 k := p[i];
19 p[i] := p[j];
20 p[j] := k;
21 k := d[i];
22 d[i] := d[j];
23 d[j] := k;
24 inc(i);
25 dec(j);
26 end;
27 until i>j;
28 if j>b then qsort(b, j);
29 if i<e then qsort(i, e);
30 end;
31
32 function lowbit(x: longint): longint;
33 begin
34 exit(x and (-x));
35 end;
36
37 procedure up(x, s: longint);
38 begin
39 while x<=n do
40 begin
41 tree[x] := tree[x] + s;
42 x := x + lowbit(x);
43 end;
44 end;
45
46 function getsum(x: longint): longint;
47 begin
48 getsum := 0;
49 while x>=1 do
50 begin
51 getsum := getsum + tree[x];
52 x := x - lowbit(x);
53 end;
54 end;
55
56 procedure main;
57 var
58 i, now: longint;
59 begin
60 readln(n);
61 while n<>0 do
62 begin
63 for i := 1 to n do
64 begin
65 readln(d[i]);
66 p[i] := i;
67 end;
68 qsort(1, n);
69 for i := 1 to n do
70 a[p[i]] := i;
71 fillchar(tree, sizeof(tree), 0);
72 ans := 0;
73 now := 0;
74 for i := 1 to n do
75 begin
76 if (i=1)or(d[i]<>d[i-1]) then inc(now);
77 a[p[i]] := now;
78 end;
79 for i := n downto 1 do
80 begin
81 up(a[i], 1);
82 ans := ans + getsum(a[i]-1);
83 end;
84 writeln(ans);
85 readln(n);
86
87 end;
88 end;
89
90 begin
91 assign(input,'test.in'); reset(input);
92 assign(output,'test.out'); rewrite(output);
93
94 main;
95
96 close(input); close(output);
97 end.