题意很简单,看案例就能懂,一个长度为n的序列,要重新排序,升序,每一次拿这个数跟后面所有数比较,需要移动尽可能往后面移动,问需要操作几次
对案例进行分析,从后往前面判,若发现前面有比当前这个数大的数答案就加1,但是发现后面很难讨论清楚,还得正向来分析,当前这个数,若后面有数字比它小,那就肯定需要操作一次的,由此想到了树状数组求逆序数中的一个操作,树状数组求逆序数就是需要先求出当前树状数组里面有多少个数比当前这个数小,于是想到了,把这个数组里的数字从后面往前面 一个一个加进树状数组里,每加一个,就判断树状数组里有没有比当前数字小的数,有答案就加1,能这样做的原因还有一个,就是题目强调了,这个序列里的数字肯定是 1到n的不同数字
int t;
int n;
int nnum[1000000 + 55];
int c[1000000 + 55];
int Case = 0;
void init() {
memset(nnum,0,sizeof(nnum));
memset(c,0,sizeof(c));
}
bool input() {
while(cin>>n) {
for(int i=1;i<=n;i++)scanf("%d",&nnum[i]);
return false;
}
return true;
}
int lowbit(int x) {
return x&(-x);
}
void add(int i,int val) {
while(i <= n) {
c[i] += val;
i += lowbit(i);
}
}
int get_sum(int i) {
int sum = 0;
while(i > 0) {
sum += c[i];
i -= lowbit(i);
}
return sum;
}
void cal() {
int ans = 0;
for(int i=n;i>0;i--) {
add(nnum[i],1);
int now = get_sum(nnum[i] - 1);
if(now > 0)ans++;
}
printf("Case #%d: %d\n",++Case,ans);
}
void output() {
}
int main() {
cin>>t;
while(t--) {
init();
if(input())return 0;
cal();
output();
}
return 0;
}