归并模板& P1908 逆序对
2016-12-15 13:25
253 查看
写法1,先开一个新的数组赋值。
写法2,后开一个新的数组赋值。
Once Self
题目描述
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai > aj且i < j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
输入输出格式
输入格式:
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。
输出格式:
给定序列中逆序对的数目。
输入输出样例
输入样例#1:
6
5 4 2 6 3 1
输出样例#1:
11
/*6
12 3 1 2 45 3
out 7*/
说明
对于50%的数据,n≤2500
对于100%的数据,n≤40000。
树状数组求逆序对
#include<iostream> #include<cstdio> using namespace std; int n,a[1001],c[1001]; void merge(int l,int r) { if(l>=r) return; int mid=(l+r)/2; merge(l,mid); merge(mid+1,r); for(int i=l;i<=r;i++) c[i]=a[i]; //c[l...mid],c[mid+1,r] int i=l,j=mid+1; for(int k=l;k<=r;k++)//a[k]要重新赋值 { if(i>mid) a[k]=c[j],j++; else if(j>r) a[k]=c[i],i++; else if(c[i]<c[j]) a[k]=c[i],i++; else a[k]=c[j],j++; } } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; merge(1,n); for(int i=1;i<=n;i++) cout<<a[i]<<" "; }
写法2,后开一个新的数组赋值。
Once Self
#include<iostream> #include<cstdio> using namespace std; int a[1001],c[1001]; void merge(int l,int r) { if(l>=r) return; int mid=(l+r)/2; merge(l,mid); merge(mid+1,r); int i=l,j=mid+1,k=l; while(i<=mid && j<=r) { if(a[i]<a[j]) c[k++]=a[i],i++; else 4000 c[k++]=a[j],j++; } while(i>mid && k<=r) c[k++]=a[j],j++; while(j>r && k<=r) c[k++]=a[i],i++; for(int k=l;k<=r;k++) a[k]=c[k];//c[1] c[2] c[3] c[4] c[5] } int main() { int n;cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; merge(1,n); for(int i=1;i<=n;i++) cout<<a[i]<<" "; }
题目描述
猫猫TOM和小老鼠JERRY最近又较量上了,但是毕竟都是成年人,他们已经不喜欢再玩那种你追我赶的游戏,现在他们喜欢玩统计。最近,TOM老猫查阅到一个人类称之为“逆序对”的东西,这东西是这样定义的:对于给定的一段正整数序列,逆序对就是序列中ai > aj且i < j的有序对。知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目。
输入输出格式
输入格式:
第一行,一个数n,表示序列中有n个数。
第二行n个数,表示给定的序列。
输出格式:
给定序列中逆序对的数目。
输入输出样例
输入样例#1:
6
5 4 2 6 3 1
输出样例#1:
11
/*6
12 3 1 2 45 3
out 7*/
说明
对于50%的数据,n≤2500
对于100%的数据,n≤40000。
2 6 7 8 1 3 4 5//<-正着想很麻烦,倒着想很简单 i j j j
#include<iostream> #include<cstdio> using namespace std; int n,a[40005],c[40005],cnt; void merge(int l,int r) { if(l>=r) return; int mid=(l+r)/2; merge(l,mid); merge(mid+1,r); for(int i=l;i<=r;i++) c[i]=a[i]; //c[l...mid],c[mid+1,r] int i=l,j=mid+1,t=0; for(int k=l;k<=r;k++)// { if(i>mid) a[k]=c[j],j++; else if(j>r) a[k]=c[i],i++; else if(c[i]>c[j]) a[k]=c[j],j++,cnt+=mid-i+1;//注意这的写法及顺序 (开始是相反的写法,很麻烦) else a[k]=c[i],i++; } } int main() { cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; merge(1,n); cout<<cnt<<endl; }
#include<iostream> #include<cstdio> using namespace std; int a[40005],c[40005],ans; void merge(int l,int r) { if(l>=r) return; int mid=(l+r)/2; merge(l,mid); merge(mid+1,r); int i=l,j=mid+1,k=l; while(i<=mid && j<=r) { if(a[i]>a[j]) { ans+=j-k;//或者mid-i+1 c[k++]=a[j],j++; } else c[k++]=a[i],i++; } while(i>mid && k<=r ) c[k++]=a[j],j++; while(j>r && k<=r ) c[k++]=a[i],i++; for(int k=l;k<=r;k++) a[k]=c[k];//c[1] c[2] c[3] c[4] c[5] } int main() { int n;cin>>n; for(int i=1;i<=n;i++)cin>>a[i]; merge(1,n); cout<<ans<<endl; }
树状数组求逆序对
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<algorithm> using namespace std; int n,a[1005],b[1005],c[1005],f[1005],res;//***** void add(int x,int y) { while(x<=n) { f[x]+=y; x+=x&-x;//110+10->1000 0101+1->0110 } } int query(int x)//查询前缀和 { int sum=0; while(x) { sum+=f[x]; x-=x&-x; } return sum; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]);b[i]=a[i]; } sort(b+1,b+n+1); int u=unique(b+1,b+n+1)-(b+1);//去重 for(int i=1;i<=n;i++) c[i]=lower_bound(b+1,b+n+1,a[i])-b;//a[i]这个数在原序列中排第几 // for(int i=1;i<=n;i++) // cout<<c[i]<<" "; // cout<<endl; //a[] 3 5 1 4 3 1-->9 //c[] 2 4 1 3 2 1 // 1 2 3 4 //4进来时,求前缀和,那么3 5 1被加1,则前缀和是3 和5 组成的和 //然后读入一个,查询一下前缀和 for(int i=1;i<=n;i++) { // cout<<"Q: "<<query(c[i])<<endl; res+=(i-1)-query(c[i]); add(c[i],1); } cout<<res<<endl; } /*对于相同的数,比如1的前面有个1,但是它在算前面比它小的数时,确实0 因此,在树状数组中应该包含它自己,将先add再query,改成先query再add,且query时要包含自己*/
相关文章推荐
- HiHoCoder-第三十九周--二分·归并排序之逆序对
- #1141 : 二分·归并排序之逆序对(归并排序)
- 归并求逆序对【模板】
- 归并算法实现求解逆序对【模板】
- 归并排序 & 数组中的逆序对 【java实现】
- 【每日算法】归并排序及其应用(逆序对&合并有序链表)
- 求逆序对 ----归并排 & 树状数组
- 【hiho39】二分·归并排序之逆序对
- poj2299Ultra-QuickSort【树状数组求逆序数、离散化】、【归并排序模板】
- 数据结构:归并排序 && 逆序对统计
- hihocoder #1141 : 二分·归并排序之逆序对
- 求逆序对常用的两种算法 ----归并排 & 树状数组
- 笔试算法题(32):归并算法求逆序对 & 将数组元素转换为数组中剩下的其他元素的乘积
- hihoCoder 1141 二分·归并排序之逆序对
- hihoCoder_二分·归并排序之逆序对
- vs2005中使用模板出现"LNK2019 - Unresolved external Symbol" 错误
- Community Server-->模板定制处理
- 将开源博客模板导入Eclipse并发布到Tomcat时猫前面有个"!"
- 编写T4模板进行代码生成无法避免的两个话题:"Assembly Locking"&"Debug"
- JOJ 2731 凸包模板题 && 贴个自己写的Graham凸包模板