1. 程式人生 > >bzoj 3580 冒泡排序 亂搞+思維

bzoj 3580 冒泡排序 亂搞+思維

亂搞 stdin mit bit long def 相對 cstring pen

冒泡排序

Time Limit: 15 Sec Memory Limit: 256 MB
Submit: 243 Solved: 108
[Submit][Status][Discuss]

Description

  下面是一段實現冒泡排序算法的C++代碼:

  for (int i=1;i<n;i++)
  for (int j=1;j<=n-i;j++)
  if (a[j]>a[j+1])
  swap(a[j],a[j+1]);

  其中待排序的a數組是一個1~n的排列,swap函數將交換數組中對應位置的值。
  對於給定的數組a以及給定的非負整數k,使用這段代碼執行了正好k次swap操作之後數組a中元素的值會是什麽樣的呢?

Input

  輸入文件共2行。
  第1行包含空格隔開的一個正整數n和一個非負整數k;
  第2行包含n個空格隔開的互不相同的正整數,表示初始時a數組中的排列。

Output

  輸出文件共1行。
  若在執行完整個代碼之後執行swap的次數仍不夠k,那麽輸出一個字符串”Impossible!”(不含引號),否則按順序輸出執行swap操作k次之後數組a的每一個元素,用空格隔開。

Sample Input

1 1
1

Sample Output

Impossible!

HINT

n<=10^6


k<=10^12

題解:這道題目的話,首先要去分析冒泡排序,設g[x]表示一個數前面比其大的個數,

那麽交換z次後,其前面比它大的個數絕對減少min(g[x],z),因為每一輪交換必定會交換下去一個比它大的數

所以可以二分出哪一輪。

然後二分出那一輪後

我們發現,g[i]<=x的話,那這個數一定排序完畢了。而對於g[i]>x的部分,他們相對於原數列的位置不變。

這樣就可以求出做了x次外層循環後的結果了

 1 #include<cstring>
 2 #include<iostream>
 3 #include<algorithm>
 4
#include<cstdio> 5 #include<cmath> 6 7 #define ll long long 8 #define N 1000007 9 using namespace std; 10 inline ll read() 11 { 12 ll x=0,f=1;char ch=getchar(); 13 while(!isdigit(ch)){if(ch==-)f=-1;ch=getchar();} 14 while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-0;ch=getchar();} 15 return x*f; 16 } 17 18 int n;ll k; 19 int a[N],mx[N],b[N],fz[N]; 20 bool boo[N]; 21 int tree[N]; 22 23 inline int lowbit(int x){return x&(-x);} 24 int query(int x) 25 { 26 int res=0; 27 for (int i=x;i>=1;i-=lowbit(i)) 28 res+=tree[i]; 29 return res; 30 } 31 void add(int x) 32 { 33 for (int i=x;i<=n+1;i+=lowbit(i)) 34 tree[i]+=1; 35 } 36 ll calc(int x) 37 { 38 ll res=0; 39 for (int i=1;i<=n;i++) 40 res+=min(mx[i],x); 41 return res; 42 } 43 int main() 44 { 45 freopen("fzy.in","r",stdin); 46 freopen("fzy.out","w",stdout); 47 48 n=read(),k=read(); 49 for (int i=1;i<=n;i++) 50 a[i]=read(); 51 for (int i=1;i<=n;i++) 52 { 53 mx[i]=query(n+1)-query(a[i]); 54 add(a[i]); 55 } 56 int l=0,r=n; 57 while(l<r) 58 { 59 int mid=(l+r+1)>>1; 60 if (calc(mid)>=k) r=mid-1; 61 else l=mid; 62 } 63 if (l==n) 64 { 65 puts("Impossible!"); 66 return 0; 67 } 68 k-=calc(l);int num=0; 69 for (int i=1;i<=n;i++) 70 if (mx[i]>r) b[i-r]=a[i]; 71 else fz[++num]=a[i]; 72 sort(fz+1,fz+num+1); 73 num=0; 74 for (int i=1;i<=n;i++) 75 if (b[i]==0) b[i]=fz[++num]; 76 for (int i=1;i<n;i++) 77 if (b[i]>b[i+1]) 78 { 79 swap(b[i],b[i+1]); 80 k--;if (!k) break; 81 } 82 for (int i=1;i<=n;i++) 83 printf("%d ",b[i]); 84 }

bzoj 3580 冒泡排序 亂搞+思維