18.12.20 DSA 重要逆序对

Posted yalphait

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18.12.20 DSA 重要逆序对相关的知识,希望对你有一定的参考价值。

描述

给定N个数的序列a1,a2,...aN,定义一个数对(ai, aj)为“重要逆序对”的充要条件为 i < j 且 ai > 2aj。求给定序列中“重要逆序对”的个数。

输入

第一行为序列中数字的个数N(1 ≤ N ≤ 200000)。
第二行为序列a1, a2 ... aN(0 ≤a ≤ 10000000),由空格分开。输出输出一个整数,为给序列中“重要逆序对”的个数。

样例输入

10
0 9 8 7 6 5 4 3 2 1

样例输出

16

提示

如果使用printf输出long long类型,请用%lld
数据范围
对于40%的数据,有N ≤ 1000。

技术分享图片
 1 #include <iostream>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <stack>
 5 #include <string>
 6 #include <math.h>
 7 #include <queue>
 8 #include <stdio.h>
 9 #include <string.h>
10 #include <set>
11 #include <vector>
12 #include <fstream>
13 #define maxn 200005
14 #define inf 999999
15 #define cha 127
16 #define eps 1e-6
17 using namespace std;
18 
19 long long ans;
20 long num[maxn],tmp[maxn];
21 int n;
22 
23 void mysort(int left,int right) {
24     if (left == right)return;
25     int mid = (left + right) / 2;
26     mysort(left, mid), mysort(mid + 1, right);
27     int i = left, j = mid + 1, p = left, t = left;
28     while (i <= mid && j <= right) {
29         if (num[i] <= num[j])
30             tmp[p++]=num[i++];
31         else {
32             while (num[t] <= 2 * num[j]&&t<=mid)
33                 t++;
34             if (num[t] > 2 * num[j])
35                 ans += mid - t + 1;
36             tmp[p++] = num[j++];
37         }
38     }
39     while (i <= mid)
40         tmp[p++] = num[i++];
41     while (j <= right)
42         tmp[p++] = num[j++];
43     for (int i = left; i <= right; i++)
44         num[i] = tmp[i];
45 }
46 
47 void init() {
48     scanf("%d", &n);
49     for (int i = 1; i <= n; i++)
50         scanf("%ld", &num[i]);
51     mysort(1, n);
52     printf("%lld
", ans);
53 }
54 
55 int main() {
56     init();
57     return 0;
58 }
View Code

好像是把maxn写错了一直TLE……哭了

用同一个指针变量指示有点难想

以上是关于18.12.20 DSA 重要逆序对的主要内容,如果未能解决你的问题,请参考以下文章

LightHouse/归并排序

归并排序 逆序对

使用GO代码实现 百度联盟媒体平台的DSA签名

使用GO代码实现 百度联盟媒体平台的DSA签名

[AHOI2008]逆序对

编程算法 - 数组中的逆序对 代码(C)