标签:下标 bsp owb 状态 ret stream mda 需要 参考
https://www.luogu.com.cn/problem/P1908
输入:9 -1 18 5
输出 3.
输入之后对应的结构体就会变成这样
val:9 -1 18 5
id: 1 2 3 4
排好序之后就变成了
val : -1 5 9 18
id: 2 4 1 3
2 4 1 3 的逆序数 也是3
这样原来是输入9,就把t[9]置为1,输入18,就把t[18]置为1,最后遍历t数组到输入数字的最大值,统计出现过的次数,如果输入一个1000000,就要遍历t数组到t【1000000】
现在使用id等价代替原数组,只需要输入元素个数的空间即可,节省了数组空间
如果遇到相等的元素,就使用id(即输入的顺序)区分,这样后输入的相等元素的id大,在进行id等价转换的时候它的转换情况偏小(自己的id大了,转换后相对于自己的数大了,那么找自己前面比自己大的数就有可能结果偏小),但是前面还有一个与自己数字相等的元素,它的id是准确的,也就是最后不会影响结果
#include<iostream> #include<cstdio> #include<algorithm> using namespace std; struct node { long long val; int id; }a[500005]; long long c[500005]; int n; bool cmp(struct node &a, struct node&b) { if (a.val == b.val)return a.id < b.id; return a.val < b.val; } int lowbit(int x) { return x&(-x); } void update(int i, int k) { while (i <= n) { c[i] += k; i += lowbit(i); } } long long getsum(int i) { long long res = 0; while (i > 0) { res += c[i]; i -= lowbit(i); } return res; } int main() { int aa, bb, cc,dd; scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%lld", &a[i].val); a[i].id = i; } sort(a + 1, a + n + 1, cmp); long long answer = 0; for (int i = 1; i <= n; i++) { update(a[i].id,1); answer += i - getsum(a[i].id);//用来存储原数第i个数的order下标是什么 } printf("%lld\n", answer); }
参考:https://www.jianshu.com/p/8a4081f0ec20
https://blog.csdn.net/m0_38033475/article/details/80330157
标签:下标 bsp owb 状态 ret stream mda 需要 参考
原文地址:https://www.cnblogs.com/Jason66661010/p/12827953.html