Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 10609 | Accepted: 6797 |
Description
Input
Output
Sample Input
5 1 2 1 0
Sample Output
2 4 5 3 1
题意:有一个序列a:1,2,…,N(2 <= N <= 8,000). 现该序列为乱序,已知第i个数前面的有a[i]个小于它的数。求出该序列的排列方式。
暴力求解:O(n*n)
1 #include <iostream> 2 #include <cstdio> 3 #include <set> 4 using namespace std; 5 int num[10000],a[10000]; 6 int main() 7 { 8 int n; 9 int i,j; 10 freopen("in.txt","r",stdin); 11 while(scanf("%d",&n)!=EOF) 12 { 13 int k=0; 14 set<int> s; 15 set<int>::iterator p; 16 for(i=2;i<=n;i++) 17 scanf("%d",&a[i]); 18 for(i=0;i<n;i++) 19 s.insert(i+1); 20 for(i=n;i>=2;i--) 21 { 22 p=s.begin(); 23 while(a[i]--) p++; 24 num[i]=*p; 25 s.erase(*p); 26 } 27 num[i]=*s.begin(); 28 for(i=1;i<=n;i++) 29 printf("%d\n",num[i]); 30 } 31 }
树状数组 O(nlogn)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 int n; 6 int a[10000],bit[10000]; 7 int num[10000]; 8 int lowbit(int i) 9 { 10 return i&-i; 11 } 12 void add(int i,int s) 13 { 14 while(i<=n) 15 { 16 bit[i]+=s; 17 i=i+lowbit(i); 18 } 19 } 20 int sum(int i) 21 { 22 int s=0; 23 while(i>0) 24 { 25 s+=bit[i]; 26 i=i-lowbit(i); 27 } 28 return s; 29 } 30 int main() 31 { 32 int i,j; 33 freopen("in.txt","r",stdin); 34 while(scanf("%d",&n)!=EOF) 35 { 36 int s=0; 37 memset(bit,0,sizeof(bit)); 38 for(i=2;i<=n;i++) 39 scanf("%d",&a[i]); 40 for(i=1;i<=n;i++) 41 add(i,1); 42 for(i=n;i>=2;i--) 43 { 44 int l=1,r=n,mid; 45 int tem=a[i]+1,p; 46 while(l<=r) 47 { 48 int mid=(r+l)/2; 49 if(sum(mid)>=tem) 50 { 51 p=mid; 52 r=mid-1; 53 } 54 else 55 { 56 l=mid+1; 57 } 58 } 59 s+=p; 60 num[i]=p; 61 add(p,-1); 62 } 63 num[1]=(n+1)*n/2-s; 64 for(i=1;i<=n;i++) 65 printf("%d\n",num[i]); 66 } 67 }
原文:http://www.cnblogs.com/a1225234/p/5035536.html