洛谷 P4378 [USACO18OPEN]Out of Sorts S(树状数组求冒泡排序循环次数)

传送门:Problem P4378

 https://www.cnblogs.com/violet-acmer/p/9833502.html

  要回宿舍休息了,题解明天再补吧。

题解:

  定义一数组 a[maxn]
  考察冒泡排序的本质。

  冒泡排序,每次会把最大的数直接沉底,但是比较小的数,会往前面缓慢冒泡。

  具体来说,如果一个数 val 在数组有序后的排名是 i ,但是目前位置在 i 之后,那么,每次循环,val 必然会往前面移动一位。

因为前面必然会有一个比 val 大的数往后沉。

  swap的次数,就是逆序对数

  循环的次数,就是max( i 前比a[i]大的数的个数)(i=1,2,3,......,n)

  注意事项:

  (1):首先需要做的是离散化原数组,因为 a[i] 的值最大可达 1e9,但 n 最大才 1e5,注意在排序的时候,对于值相同的两个数,初始编号小的在前。

  (2):最终结果要额外 +1

AC代码:

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 using namespace std;
 5 #define lowbit(x) (x&(-x))
 6 const int maxn=1e5+50;
 7 
 8 int N;
 9 struct Node
10 {
11     int val;
12     int id;//存储初始编号
13     int newVal;//存储离散化后 val 对应的新值
14 }a[maxn];
15 //==============BIT===================
16 int bit[maxn];
17 void Add(int x)
18 {
19     while(x <= N)
20     {
21         bit[x]++;
22         x += lowbit(x);
23     }
24 }
25 int Sum(int x)
26 {
27     int sum=0;
28     while(x > 0)
29     {
30         sum += bit[x];
31         x -= lowbit(x);
32     }
33     return sum;
34 }
35 //=====================================
36 bool cmp(Node _a,Node _b){
37     //值不同,值小的在前;值相同,初始编号小的在前,保证排序的稳定性
38     return _a.val < _b.val || (_a.val == _b.val && _a.id < _b.id);
39 }
40 bool cmp1(Node _a,Node _b){
41     return _a.id < _b.id;
42 }
43 void Solve()
44 {
45     sort(a+1,a+N+1,cmp);
46     for(int i=1;i <= N;++i)
47         a[i].newVal=i;//离散化后的对应的值,虽然可能大小变了,但其对应的相对次序是不变的
48     sort(a+1,a+N+1,cmp1);//恢复原数组对应的顺序
49     int res=0;
50     for(int i=1;i <= N;++i)
51     {
52         //Sum(a[i].newVal) : i 之前,数值不大于a[i].newVal 的个数
53         //i-1-Sum(a[i].newVal) : i 之前,数值大于a[i].newVal的个数
54         //而答案就是 max(i-1-Sum(a[i].newVal)
55         res=max(res,i-1-Sum(a[i].newVal));
56         Add(a[i].newVal);
57     }
58     printf("%d
",res+1);//最终结果要加1,因为不管当前交换完后是否有序,都需要额外输出一个 moo 来判断是否有序
59 }
60 int main()
61 {
62     scanf("%d",&N);
63     for(int i=1;i <= N;++i)
64     {
65         scanf("%d",&a[i].val);
66         a[i].id=i;
67     }
68     Solve();
69 }
View Code

  

原文地址:https://www.cnblogs.com/violet-acmer/p/9833435.html