[USACO18OPEN] Out of Sorts P JZOJ 100136 冒泡的胖头鱼(冒泡排序性质)

题解:

显然对整个序列考虑不行,不如对每一个元素单独考虑。

一个元素x在x和x+1都成为分割点前显然会被一直计算答案,设(T(x))表示x分割点出现的时间。

那么(Ans=sum_{i=1}^n max(T(i-1),T(i)))

众所周知,冒泡排序都是去考虑每一个元素的往左移动,而不是往右移动。

对冒泡排序的一个元素(a[i]),若它前面有(k)个比他大的数,那么前(k)轮它都会往前移动一格。

对于这题,只要(1..x)的元素全部退到(x)以前,就有(x)这个分割点了。

所以设(b[i])(i)大的元素所在的位置,(T(x)=max(b[i]-x)(iin[1,x]))

这题有相同的元素,由于冒泡排序是稳定排序,所以相同的元素就考虑它们原来的位置就好了。

Code:

#include<bits/stdc++.h>
#define fo(i, x, y) for(int i = x, _b = y; i <= _b; i ++)
#define ff(i, x, y) for(int i = x, _b = y; i <  _b; i ++)
#define fd(i, x, y) for(int i = x, _b = y; i >= _b; i --)
#define ll long long
#define pp printf
#define hh pp("
")
using namespace std;

const int N = 1e5 + 5;

int n, a[N], b[N], mx;
ll ans;

int cmpb(int x, int y) {
	if(a[x] == a[y]) return x < y;
	return a[x] < a[y];
}

int main() {
	scanf("%d", &n);
	fo(i, 1, n) scanf("%d", &a[i]), b[i] = i;
	sort(b + 1, b + n + 1, cmpb);
	int t1 = 0, t2;
	fo(i, 1, n) {
		mx = max(mx, b[i]);
		t2 = max(mx - i, 1);
		ans += max(t1, t2); t1 = t2;
	}
	pp("%lld
", ans);
}
原文地址:https://www.cnblogs.com/coldchair/p/12361555.html