HDU 5775 Bubble Sort(冒泡排序)
Posted Simon_X
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5775 Bubble Sort(冒泡排序)相关的知识,希望对你有一定的参考价值。
HDU 5775 Bubble Sort(冒泡排序)
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Problem Description - 题目描述
P is a permutation of the integers from 1 to N(index starting from 1).
Here is the code of Bubble Sort in C++.
![](https://image.cha138.com/20210610/80d8dffb12c549ab9cd89a50164e5c13.jpg)
P是整数数列1到N的乱序排列(下标从1开始)。
以下是C++的冒泡排序代码。
for(int i=1;i<=N;++i) for(int j=N,t;j>i;—j) if(P[j-1] > P[j]) t=P[j],P[j]=P[j-1],P[j-1]=t;
After the sort, the array is in increasing order. ?? wants to know the absolute values of difference of rightmost place and leftmost place for every number it reached.
![](https://image.cha138.com/20210610/80d8dffb12c549ab9cd89a50164e5c13.jpg)
冒泡后,数组变为升序排列。??想知道每个数所能到达的最右端与最左端(下标)差的绝对值是多少。
Input - 输入
The first line of the input gives the number of test cases T; T test cases follow.
Each consists of one line with one integer N, followed by another line with a permutation of the integers from 1 to N, inclusive.
limits
T <= 20
1 <= N <= 100000
N is larger than 10000 in only one case.
![](https://image.cha138.com/20210610/80d8dffb12c549ab9cd89a50164e5c13.jpg)
输入的第一行给定测试用例数量T,随后T组测试用例。 每组测试用例的一行为一个整数N,另一行为整数数列1到N的乱序排列。 数据范围 T <= 20 1 <= N <= 100000 只有一组测试用例的N大于10000。
Output - 输出
For each test case output “Case #x: y1 y2 … yN” (without quotes), where x is the test case number (starting from 1), and yi is the difference of rightmost place and leftmost place of number i.
![](https://image.cha138.com/20210610/80d8dffb12c549ab9cd89a50164e5c13.jpg)
对于每组测试用例输出“Case #x: y1 y2 … yN”(不含引号),x为测试用例的编号(从1开始),yi表示数字i最右端与最左端位置的差。
Sample Input - 输入样例
2 3 3 1 2 3 1 2 3
Sample Output - 输出样例
Case #1: 1 1 2 Case #2: 0 0 0
Hint - 提示
In first case, (3, 1, 2) -> (3, 1, 2) -> (1, 3, 2) -> (1, 2, 3)
the leftmost place and rightmost place of 1 is 1 and 2, 2 is 2 and 3, 3 is 1 and 3
In second case, the array has already in increasing order. So the answer of every number is 0.
![](https://image.cha138.com/20210610/80d8dffb12c549ab9cd89a50164e5c13.jpg)
在第一个样例中, (3, 1, 2) -> (3, 1, 2) -> (1, 3, 2) -> (1, 2, 3) 对于左右两端的位置,1为1与2,2为2与3,3为1与3 在第二个样例中,数组已为升序排列。因此每个数的结果都是0。
题解
暴冒泡排序,主要是和逆序数有关系,和以前做过的小朋友排队很像。
对于各个元素的移动而言,都是先向左移动,再向右移动。因此最左端的位置是可以确定的。
最左边的位置 = 初始位置 + 逆序数(右边有多少数字比其小)
最右边的位置 = max(初始位置, 末位置(下标即元素的值))。
左边 - 右边 >= 0,其实也不用取绝对值了。
最后又是(0, a)的区间求和问题,可以用线段树,也能用树状数组。
代码 C++
![](https://image.cha138.com/20210610/80d8dffb12c549ab9cd89a50164e5c13.jpg)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define mx 100005 5 int lTree[mx << 2], fidL, fidR, opn, data[mx], opt[mx]; 6 void push(int L, int R, int now){ 7 ++lTree[now]; 8 if (L == R) return; 9 int mid = L + R >> 1; 10 if (opn > mid) return push(mid + 1, R, now << 1 | 1); 11 return push(L, mid, now << 1); 12 } 13 int sum(int L, int R, int now){ 14 if (fidL <= L && R <= fidR) return lTree[now]; 15 if (fidR < L || R < fidL) return 0; 16 int mid = L + R >> 1; 17 return sum(L, mid, now << 1) + sum(mid + 1, R, now << 1 | 1); 18 } 19 int main(){ 20 int t, it, n, i, movR; 21 for (it = scanf("%d", &t); it <= t; ++it){ 22 printf("Case #%d:", it); memset(lTree, 0, sizeof(lTree)); 23 scanf("%d", &n); 24 for (i = 1; i <= n; ++i) scanf("%d", data + i); 25 for (i = n; i; --i){ 26 opn = data[i]; push(1, n + 1, 1); 27 fidL = 0; fidR = opn - 1; 28 opt[data[i]] = i + sum(1, n + 1, 1) - std::min(data[i], i); 29 } 30 for (i = 1; i <= n; ++i) printf(" %d", opt[i]); 31 puts(""); 32 } 33 return 0; 34 }
![](https://image.cha138.com/20210610/80d8dffb12c549ab9cd89a50164e5c13.jpg)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define mx 100005 5 inline int lb(int x){ return -x&x; }; 6 int data[mx], n, tr[mx], opt[mx]; 7 void push(int a){ 8 while (a <= n) ++tr[a], a += lb(a); 9 } 10 int sum(int L){ 11 int opt = 0; 12 while (L) opt += tr[L], L -= lb(L); 13 return opt; 14 } 15 int main(){ 16 int t, it, i; 17 for (it = scanf("%d", &t); it <= t; ++it){ 18 printf("Case #%d:", it); memset(tr, 0, sizeof(tr)); 19 for (i = scanf("%d", &n); i <= n; ++i) scanf("%d", data + i); 20 for (i = n; i ; --i){ 21 push(data[i]); 22 opt[data[i]] = i + sum(data[i] - 1) - std::min(data[i], i); 23 } 24 for (i = 1; i <= n; ++i) printf(" %d", opt[i]); 25 puts(""); 26 } 27 return 0; 28 }
以上是关于HDU 5775 Bubble Sort(冒泡排序)的主要内容,如果未能解决你的问题,请参考以下文章