给定一段冒泡排序的代码,要求输出每个数字能到达的最右边的位置和最左边的位置的差
因为那段冒泡排序的代码是每次选取一个最小的数,放在左边的,所以,每个数最多能到达右边的位置应该是起始位置i+右边有多少个数比它大。
它能到达的最左的位置,可以这样考虑
1、它本来应该是排去起始位置的左边的,就是它本来是一个小的数字,起始位置在末尾这种情况的话。最左边的值就是a[i]
2、它是去右边的,那么最左边的值就是起始位置,
两种取max就去可以了
#include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; typedef unsigned long long int ULL; #include <iostream> #include <sstream> #include <vector> #include <set> #include <map> #include <queue> #include <string> const int maxn = 100000 +20; int a[maxn]; int c[maxn]; int n; int dpR_min[maxn]; int ans[maxn]; int pos[maxn]; int f; int lowbit (int x)//得到x二进制末尾0的个数的2次方 2^num { return x&(-x); } void add (int pos,int val)//在第pos位加上val这个值 { while (pos<=n) //n是元素的个数 { c[pos] += val; pos += lowbit(pos); } return ; } int get_sum (int pos) //求解:1--pos的总和 { int ans = 0; while (pos) { ans += c[pos]; pos -= lowbit(pos); } return ans; } void work () { scanf("%d",&n); for (int i=1; i<=n; ++i) { scanf("%d",&a[i]); pos[a[i]]=i; } memset(c,0,sizeof c); for (int i=n; i>=1; --i) { dpR_min[i] = get_sum(a[i]-1); add(a[i],1); } for (int i=1;i<=n;++i) { int end = pos[a[i]] + dpR_min[pos[a[i]]];//看看它最右能去哪里 //如果这个数字是要去右边 int tR = end - pos[a[i]]; //去左边 int tL = end - a[i]; ans[a[i]] = max(tR,tL); } printf ("Case #%d:",++f); for (int i=1;i<=n;++i) { printf (" %d",ans[i]); } printf ("\n"); } int main() { #ifdef local freopen("data.txt","r",stdin); #endif int t; scanf("%d",&t); while (t--) work(); return 0; }
题目要看懂。。题目看得我头疼
时间: 2024-10-05 10:38:28