hdu 5122 K.Bro Sorting【思维+树状数组】

来源:互联网 发布:淘宝宝贝类目是什么 编辑:程序博客网 时间:2024/05/22 05:38

K.Bro Sorting

Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 512000/512000 K (Java/Others)
Total Submission(s): 2390    Accepted Submission(s): 1114

Problem Description

Matt’s friend K.Bro is an ACMer.

Yesterday, K.Bro learnt an algorithm: Bubble sort. Bubble sort will compare each pair of adjacent items and swap them if they are in the wrong order. The process repeats until no swap is needed.

Today, K.Bro comes up with a new algorithm and names it K.Bro Sorting.

There are many rounds in K.Bro Sorting. For each round, K.Bro chooses a number, and keeps swapping it with its next number while the next number is less than it. For example, if the sequence is “1 4 3 2 5”, and K.Bro chooses “4”, he will get “1 3 2 4 5” after this round. K.Bro Sorting is similar to Bubble sort, but it’s a randomized algorithm because K.Bro will choose a random number at the beginning of each round. K.Bro wants to know that, for a given sequence, how many rounds are needed to sort this sequence in the best situation. In other words, you should answer the minimal number of rounds needed to sort the sequence into ascending order. To simplify the problem, K.Bro promises that the sequence is a permutation of 1, 2, . . . , N .

Input

The first line contains only one integer T (T ≤ 200), which indicates the number of test cases. For each test case, the first line contains an integer N (1 ≤ N ≤ 106).

The second line contains N integers ai (1 ≤ ai ≤ N ), denoting the sequence K.Bro gives you.

The sum of N in all test cases would not exceed 3 × 106.

Output

For each test case, output a single line “Case #x: y”, where x is the case number (starting from 1), y is the minimal number of rounds needed to sort the sequence.

Sample Input

2

5

5 4 3 2 1

5

5 1 2 3 4

Sample Output

Case #1: 4

Case #2: 1

Hint

In the second sample, we choose “5” so that after the first round, sequence becomes “1 2 3 4 5”, and the algorithm completes.

Source

2014ACM/ICPC亚洲区北京站-重现赛(感谢北师和上交)


题目大意:

给你N个数,每一次选择一个数,然后和其之后的数判断,就和冒泡排序一样,如果这个数大于后边那个数,那么交换即可,一直交换到不能交换为止,问最少选择几次这样的操作就能够使得整个序列是递增的。


思路:


1、一开始以为a【i】>a【i+1】output++即可,但是一组数据就能hack掉这样的思路:

4

1 3 4 2


2、正确的思路是这样的:如果当前数的后边有比他小的数存在,那么这个数就是一定要和那个数进行交换,那么当前数也就是说一定要选择上,因为数据范围比较大,要想做到这一点的统计工作直接暴力是不行的,那么我们用树状数组优化即可。


3、将输入的数据倒序之后,每添加当前数据之前,先查询一下当前数之前有没有比这个数小的,如果有output++即可,然后添加上当前数据到树里边。


Ac代码:


#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;int a[1000400];int tree[1000400];int n;int lowbit(int x){    return x&(-x);}int sum(int x){    int sum=0;    while(x>0)    {        sum+=tree[x];        x-=lowbit(x);    }    return sum;}void add(int x,int c){    while(x<=n)    {        tree[x]+=c;        x+=lowbit(x);    }}int main(){    int t;    int kase=0;    scanf("%d",&t);    while(t--)    {        scanf("%d",&n);        memset(tree,0,sizeof(tree));        int output=0;        for(int i=0;i<n;i++)        {            scanf("%d",&a[i]);        }        reverse(a,a+n);        for(int i=0;i<n;i++)        {            int tmp=sum(a[i]);            if(tmp>0)output++;            add(a[i],1);        }        printf("Case #%d: %d\n",++kase,output);    }}





0 0