HDU 5775:Bubble Sort(树状数组)

本文介绍了一个关于冒泡排序的问题,即求出数组中每个元素在排序过程中能达到的最左与最右位置的距离差。通过使用树状数组记录和更新元素位置信息的方法,实现了高效求解。

http://acm.hdu.edu.cn/showproblem.php?pid=5775

 

Bubble Sort

 

 

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++.

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.
 

 

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. 
 
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.
 
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.
 
题意:求出1-n里面各个数在冒泡排序里面可以达到的最右距离和最左距离之差是多少。
 1 #include <cstring>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cmath>
 6 using namespace std;
 7 #define N 100005
 8 /*
 9 树状数组
10 从右边往左扫看右边有多少个数是小于当前位置的数的,
11 然后可以达到的最右距离就是最初始的位置加上小于它的数的数量
12 可以达到的最左距离是min(最初始的位置,i)
13 所以最右减去最左就是i的答案了.
14 */
15 int bit[N];
16 int num[N], tmp[N], r[N];
17 
18 int lowbit(int x)
19 {
20     return x & (-x);
21 }
22 
23 void update(int x)
24 {
25     while(x <= N) {
26         bit[x] += 1;
27         x += lowbit(x);
28     }
29 }
30 
31 int query(int x)
32 {
33     int ans = 0;
34     while(x) {
35         ans += bit[x];
36         x -= lowbit(x);
37     }
38     return ans;
39 }
40 
41 int main()
42 {
43     int t;
44     scanf("%d", &t);
45     for(int cas = 1; cas <= t; cas++) {
46         memset(bit, 0, sizeof(bit));
47         int n;
48         scanf("%d", &n);
49         for(int i = 1; i <= n; i++){
50             scanf("%d", num+i);
51             tmp[num[i]] = i;
52         }
53         for(int i = n; i > 0; i--) {
54             update(num[i]);
55             r[num[i]] = query(num[i] - 1);
56         }
57 
58         printf("Case #%d: ", cas);
59         for(int i = 1; i <= n; i++) {
60             if(i != n) printf("%d ", abs(tmp[i]+r[i] - min(tmp[i], i)));
61             else printf("%d\n", abs(tmp[i]+r[i] - min(tmp[i], i)));
62         }
63     }
64     return 0;
65 }

 

转载于:https://www.cnblogs.com/fightfordream/p/5719743.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值