题目链接:点击这里
题意:给出一个序列,求每一个数字在冒泡排序中出现的最大最小下标差。
从小到大考虑每一个数组,一个数字右边有多少个比他大的数字就是他右移的数量。用树状数组维护下就好了。
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
using namespace std;
#define maxn 100005
int c[maxn], pre[maxn];
struct node {
int num, pos;
bool operator < (const node &a) const {
return num < a.num;
}
} a[maxn];
int n;
int l[maxn], r[maxn];
int lowbit (int x) {
return x&(-x);
}
void add (int x) {
for (int i = x; i > 0; i -= lowbit (i)) {
c[i]++;
}
}
int query (int x) {
int ans = 0;
for (int i = x; i <= n; i += lowbit (i)) {
ans += c[i];
}
return ans;
}
int main () {
int t, kase = 0;
scanf ("%d", &t);
while (t--) {
scanf ("%d", &n);
for (int i = 1; i <= n; i++) {
scanf ("%d", &a[i].num); pre[a[i].num] = i;
a[i].pos = i;
l[a[i].num] = r[a[i].num] = i;
}
printf ("Case #%d: ", ++kase);
sort (a+1, a+1+n);
memset (c, 0, sizeof c);
for (int i = 1; i <= n; i++) {
int tmp = query (a[i].pos);
r[i] = max (pre[i]+tmp, r[i]);
l[i] = min (l[i], i);
add (a[i].pos);
}
for (int i = 1; i <= n; i++) {
printf ("%d%c", abs (r[i]-l[i]), (i == n ? '\n' : ' '));
}
}
return 0;
}