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.InputThe 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.OutputFor 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 Input233 1 231 2 3Sample Output
Case #1: 1 1 2
Case #2: 0 0 0HintIn 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的序列,让你用他给你的冒泡排序排好这些序列值之后,求出每一个数移动的左下标和右下标差的绝对值。你可以发现一个规律这个数右边有几个小于它的数,
这个数就会向右移动几位(它排好序之前的位置加上它移动的位置就是这个数的右下标),而它的左下标要么在这个数排好序之后的位置,要么在它排序之前的位置
用归并排序也可以写出这道题。思路就是在在归并排序合并的时候可以求出这个数右边有几个小于它的数
//shenjingwei #include<algorithm> #include<iostream> #include<stdio.h> #include<map> #include<vector> #include<math.h> #include<string.h> using namespace std; #define ll long long #define mod 90001 #define INF 0x3f3f3f3f #define pai (sqrt(5)+ 1)/2 #define pi acos(-1.0) ll gcd(ll a,ll b) { return b?gcd(b,a%b):a; //最大公约数 } ll lcm(ll a,ll b) { return a/gcd(a,b)*b; //最小公倍数 } ll powmod(ll a,ll b,ll MOD) { ll ans=1; while(b) { if(b%2)ans=ans*a%MOD; a=a*a%MOD; b/=2; } return ans; } //求平方数 double dpow(double a,ll b) { double ans=1.0; while(b) { if(b%2)ans=ans*a; a=a*a; b/=2; } return ans; } #define LEN 100100 struct aa { int ans; int key; int ben; } a[LEN]; void merge(aa a[], int start, int mid, int end,aa left [],aa right []) { int i, j, k; for (i = start; i <= mid; i++) /* left holds a[start..mid] */ left[i] = a[i]; for (j = mid+1; j <=end; j++) /* right holds a[mid+1..end] */ right[j] = a[j]; i = start; j=mid+1; k = start; int an=0; while (i <=mid && j <=end) { if (left[i] .key<=right[j].key) { a[k++] = left[i++]; a[k-1].ans+=an;//精辟求这个数右边有几个小于它的数 } else { an++; a[k++] = right[j++]; } } while (i <=mid) { /* left[] is not exhausted */ a[k++] = left[i++]; a[k-1].ans+=an; } while (j <= end) /* right[] is not exhausted */ { a[k++] = right[j++]; } } // merge_sort():先排序,再合并 void merge_sort(aa a[], int start, int end,aa left [],aa right []) { int mid; if (start < end) { mid = (start + end) / 2; // 分解 + 解决:Divide + Conquer merge_sort(a, start, mid,left,right); // 递归划分原数组左半边array[start...mid] merge_sort(a, mid+1, end,left,right); // 递归划分array[mid+1...end] merge(a, start, mid, end,left,right); // 合并 } } int main(void) { int n,t,case1=1,i; aa left[LEN],right[LEN]; cin>>t; while(t--) { memset(a,0,sizeof(a)); cin>>n; for(int i=1; i<=n; i++) scanf("%d",&a[i].key),a[i].ben=i; merge_sort(a, 1, n,left,right); int b[LEN]; printf("Case #%d: ",case1++); for(int i=1; i<=n; i++) { int c1,c2,c3,k1,k2; c1=a[i].key; c2=a[i].ben+a[i].ans; c3=a[i].ben; k1=max(max(c1,c2),c3); k2=min(min(c1,c2),c3); b[i]=abs(k1-k2); } for( i=1; i<n; i++) printf("%d ",b[i]); printf("%d ",b[i]); } return 0; }