Loading

2021牛客暑期多校训练营4 I. Inverse Pair(逆序对/树状数组/贪心)

链接:https://ac.nowcoder.com/acm/contest/11255/I
来源:牛客网

题目描述

For a sequence t1...nt1...n, we define the weight of it is the number of pairs (i,j)(i,j) satisfy i<jitjti>tj.

Now give you a permutation a1...na1...n, you need to choose a sequence b1...nb1...n satisfies bi∈{0,1}bi∈{0,1} to minimize the weight of sequence c1...nc1...n which satisfies ci=ai+bici=ai+bi.

输入描述:

The first line has one integer nn.

The second line has nn integers a1...na1...n.

It's guaranteed that aiai is a permutation of {1,2...n}{1,2...n}

1≤n≤2×1051≤n≤2×105

输出描述:

Output the minimum weight of c1...nc1...n you can get.

示例1

输入

复制

5
4 3 2 5 1

输出

复制

5

看到原序列是一个排列,同时每个位置最多只能添加1,想到是否添加1产生的影响可能不是很大(逆序数要求的是严格大于)。

考虑从小到大枚举排列里的数,假设枚举到x,x + 1的位置在x前面且x - 1这个数没有操作过的话就给当前的x对应的位置加上1,这样能减少一个逆序数(如果x - 1操作过,此时x再操作一次相当于x - 1进行的+1操作是无效的)。这样贪心地加完一遍以后再用树状数组统计逆序数即可。

#include <bits/stdc++.h>
using namespace std;
int n, a[200005], pos[200005], b[200005];
void add(int x, int y)
{
    for( ; x <= n; x += x & (-x)) b[x] += y;
}
int ask(int x)
{
    int ans=0;
    for(; x; x -= x & -x) ans += b[x]; 
    return ans;
}
int main() {
	cin >> n;
	for(int i = 1; i <= n; i++) {
		cin >> a[i];
		pos[a[i]] = i;
	}
	bool flag = 0;
	for(int i = 1; i <= n - 1; i++) {
		if(pos[i + 1] < pos[i] && (!flag)) {
			a[pos[i]]++;
			flag = 1;
		} else {
			flag = 0;
		}
	}
	long long ans = 0;
	for(int i = 1; i <= n; i++) {
		ans += 0ll + 1ll * ask(n) - ask(a[i]);
		add(a[i], 1);
	}
	cout << ans;
}
posted @ 2021-07-26 18:42  脂环  阅读(58)  评论(0编辑  收藏  举报