标签:题目 style 一个 opened ace ref pen UI div
题目链接 : POJ-2288
题目大意:
给你一组数,问你对这组数进行冒泡排序,需要进行多少次交换。
题目分析:
由于数据量很大,直接进行模拟冒泡排序的过程O(n2 ) 必然是不可以的。
其实对于每个数 num [ i ],要考虑这个数进行了多少次变化,只需考虑num[i]前面有多少
个数大于num[i],即计算所有的逆序对数进行相加。
为了计算逆序对数,我们可以考虑使用树状数组。
首先因为num[i]最大为1e9,无法开出这么大的数组,但是我们观察最多只有五万个数,
所以我们可以考虑进行离散化,所以首先我进行了一个自己吓懵的离散化。
即把每个数替换成50000-该数为数组中第几大的数。
(为什么不直接使用第几大数替换?
因为数组数组只能查询区间1~i 有多少个数,而我们需要考虑的是i前面有多少个数大于i,
所以直接替换不方便查询)
然后进行套用树状树状即可。
(注意如果进行查询num[i],要查询num[i]-1,因为只有严格大于的数才可以,等于的不符合条件)
给出代码:
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 int N=500000+10; 8 const int inf=1e9+10; 9 struct node 10 { 11 int id; 12 int grade; 13 }nodes[500000+10]; 14 int vis[500000+10]; 15 int num[500000+10]; 16 int bit(int x) 17 { 18 return (x&(-x)); 19 } 20 bool cmp(const node& a,const node& b) 21 { 22 return a.grade<b.grade; 23 } 24 int add(int x,int pos) 25 { 26 while(pos<=N) 27 { 28 vis[pos]+=x; 29 pos+=bit(pos); 30 } 31 return 0; 32 } 33 int sum(int pos) 34 { 35 int sum=0; 36 while(pos>0) 37 { 38 sum+=vis[pos]; 39 pos-=bit(pos); 40 } 41 return sum; 42 } 43 int main() 44 { 45 int n; 46 while(cin>>n&&n) 47 { 48 memset(vis,0,sizeof(vis)); 49 for(int i=0;i<n;i++) 50 { 51 scanf("%d",&num[i]); 52 nodes[i].grade=num[i]; 53 nodes[i].id=i; 54 } 55 sort(nodes,nodes+n,cmp); 56 int ans=500003; 57 for(int i=0;i<n;) 58 { 59 int j; 60 for(j=i;j<n&&(j==i||nodes[j].grade==nodes[j-1].grade);j++) 61 { 62 num[nodes[j].id]=ans; 63 } 64 ans--; 65 i=j; 66 } 67 /* cout<<endl; 68 for(int i=0;i<n;i++) 69 { 70 cout<<num[i]<<endl; 71 72 }*/ 73 // cout<<endl; 74 //ans=0; 75 long long int cnt=0; 76 for(int i=0;i<n;i++) 77 { 78 long long int t=sum(num[i]-1); 79 cnt+=t; 80 // cout<<t<<" *"<<endl; 81 add(1,num[i]); 82 } 83 // cout<<endl; 84 // printf("%d\n",ans); 85 cout<<cnt<<endl; 86 } 87 return 0; 88 }
标签:题目 style 一个 opened ace ref pen UI div
原文地址:http://www.cnblogs.com/DLKKILL/p/7398332.html