冒泡排序

题目大意:给定一个序列,问需要几轮冒泡排序之后才会得到一个合法序列(每一轮是指在一层for里面)

看到冒泡排序啥的就想逆序对

考虑冒泡排序的本质,每次都会把当前最大的挤到后边,然后把小的推到前边来,回想逆序对的定义,这个数字前面比它大的数字的个数,而比我大的数字,不都一定会到我后边吗?一次只会有一个到我后边,所以一定会至少有这么多\(次数_{比我大的数字}​\)轮数,然后取max即可

然后求逆序对的时候,本来是\(O(n\times logn)​\)

但是鉴于这是个排列,且最后的数字一定是有序的

所以对于\(i​\)来说,逆序对个数就是这里本应该是的数字与这里实际是的数字的差(想一想,为什么)

\(O(n)\)求,实属niub

本应该是这里的数字意味着我前边应该有\(i-1\)个数字,但是我这里仅仅是\(a[i]\),然后讨论一下\(a[i]\)的大小

  • \(a[i] > i​\),说明有某一个\(i'​\)\(i​\)的后边,我们枚举到\(i'​\)的时候会更新答案的,对我们的答案一定不会有影响
  • \(a[i]<i​\),说明我前边一定有比我大的数字

这个其实是一个很巧妙的思想,需要好好缓和两天

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <bits/stdc++.h>
#define lowbit(x) (x & -x)
#define ll long long
using namespace std;

const int N = 3e7 + 66;

int n, res;
ll S, B, C, D;
int a[N], b[N], tree[N];

inline void chenge(int x, int c)
{
for (; x <= n; x += lowbit(x)) tree[x] += c;
return;
}

inline query(int x)
{
int ret = 0;
while (x)
{
ret += tree[x];
x -= lowbit(x);
}
return ret;
}

signed main()
{
int i;

n = read(), S = read(), B = read(), C = read(), D = read();
for (i = 1; i <= n; ++ i)
{
a[i] = i;
S = (S * B + C) % D;
swap(a[i], a[(S % i) + 1]);
}

// cin >> n;
// for (i = 1; i <= n; ++ i) a[i] = read();

for (i = 1; i <= n; ++ i)
{
// chenge(a[i], 1);
// res = max(res, i - query(a[i]));
res = max(res, i - a[i]);
}
put(res);
return 0;
}