[Ybt high-efficiency advanced 4-2-2] [luogu P1908] reverse order pair

Reverse pair

Topic link: ybt high-efficiency advanced 4-2-2 / luogu P1908

General idea

Find the number of reverse pairs of a sequence.

Ideas

We consider how many numbers before it are greater than it for each position.
(If there is no such number, it can form a reverse pair with your number)

Then we consider using a tree array.
The tree array can use the number less than or equal to a number, then we use all the numbers before it minus the number less than or equal to it, that is, the number greater than it.
Then have an idea, enumerate the numbers from left to right, then put it into the tree array and find the above things. Then add up the results each time to get the total number of pairs in reverse order.

Because the tree array is stored in such a way that it is numeric, we have to discretize the array and renumber it according to the size. That's it, anyway, your reverse order is only the size relationship, there is no problem if you only change the number without changing the size relationship.

Code

#include<cstdio>
#include<algorithm>
#define ll long long

using namespace std;

struct node {
    
    
	int x, num, lx;
}a[500001];
ll tree[500001], ans;
int n;

bool cmp1(node x, node y) {
    
    
	return x.x < y.x;
}

bool cmp2(node x, node y) {
    
    
	return x.num < y.num;
}

void lsh() {
    
    
	int tmp = 0;
	sort(a + 1, a + n + 1, cmp1);
	a[1].lx = ++tmp;
	for (int i = 2; i <= n; i++)
		if (a[i].x != a[i - 1].x) a[i].lx = ++tmp;
			else a[i].lx = tmp;
	sort(a + 1, a + n + 1, cmp2);
}

void add(int x, ll y) {
    
    
	for (int i = x; i <= n; i += i & (-i))
		tree[i] += y;
}

ll ask(int x) {
    
    
	ll re = 0;
	for (int i = x; i; i -= i & (-i))
		re += tree[i];
	return re;
}

int main() {
    
    
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
    
    
		scanf("%d", &a[i].x);
		a[i].num = i;
	}
	
	lsh();//离散化重新编号
	
	for (int i = 1; i <= n; i++) {
    
    
		add(a[i].lx, 1ll);
		ans += 1ll * i - ask(a[i].lx);//逆序对=所有的对-顺序对
	}
	
	printf("%lld", ans);
	
	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_43346722/article/details/114761364