分析:贪心策略。第一行第一小对第二行第一小、第一行第二小对第二行第二小。。。类推。
即:排序,求排序的次数。
(归并排序求逆序对)【记录交换的次数即是答案】*推荐使用归并。本题最优解法。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> using namespace std; const int mod=99999997; int a[100005],b[100005]; int l[100005],r[100005]; int s[100005],t[100005]; int rr[100005]; int sum; int n; void m_sort(int x,int y) { if(y-x>1) { int m=x+(y-x>>1); int p=x,q=m,i=x; m_sort(x,m); m_sort(m,y); while(p<m || q<y) { if(q>=y || (p<m && s[p]<=s[q])) t[i++]=s[p++]; else { t[i++]=s[q++]; sum+=m-p; } } for(i=x;i<y;i++) s[i]=t[i]; } sum%=mod; } int main() { scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d",a+i); l[i]=a[i]; } for(int i=0;i<n;i++) { scanf("%d",b+i); r[i]=b[i]; } sort(l,l+n); sort(r,r+n); for(int i=0;i<n;i++) { int locB=lower_bound(r,r+n,b[i])-r; rr[locB]=i; } for(int i=0;i<n;i++) { int locA=lower_bound(l,l+n,a[i])-l; s[rr[locA]]=i; } m_sort(0,n); printf("%d",sum); return 0; }
(线段树/树状数组求逆序对)
#include<iostream> #include<cstdlib> #include<cstdio> #include<algorithm> using namespace std; struct stone { int num,c; } l1[100010],l2[100010]; int n,c[100010]; int tree[100010]; int lowbit(int x) { return (-x)&x; } bool cmp(stone x,stone y) { return x.c<y.c; } void insert(int x) { while(x<=n) { tree[x]++; x+=lowbit(x); } } int get(int x) { int sum=0; while(x>0) { sum+=tree[x]; x-=lowbit(x); } return sum; } int main() { cin>>n; for(int i=1;i<=n;i++) { scanf("%d",&l1[i].c); l1[i].num=i; } for(int i=1;i<=n;i++) { scanf("%d",&l2[i].c); l2[i].num=i; } sort(l1+1,l1+n+1,cmp); sort(l2+1,l2+n+1,cmp); long long cnt=0; for(int i=1;i<=n;i++) { c[l1[i].num]=l2[i].num; } //for(int i=1;i<=n;i++) cout<<c[i]<<" "; for(int i=1;i<=n;i++) { insert(c[i]); cnt+=i-get(c[i]); cnt=cnt%99999997; } cout<<cnt; return 0; }
std::
#include<cstdio> #include<algorithm> #define MAXN 100000 using namespace std; struct node { int x,cnt; }A[MAXN+10],B[MAXN+10]; int aa[MAXN+10]; int T[MAXN+10]; int ans=0; bool cmp(node a,node b) { return a.x<b.x; } void marge(int l,int mid,int r) { int i=l,j=mid+1,k; for(k=l;k<=r;k++) if((i<=mid)&&((j>r)||(aa[i]<=aa[j]))) T[k]=aa[i++]; else{ T[k]=aa[j++]; ans+=mid-i+1; ans%=99999997; } for(i=l;i<=r;i++) aa[i]=T[i]; } void margef(int l,int r) { if(l<r) { int mid=(l+r)/2; margef(l,mid); margef(mid+1,r); marge(l,mid,r); } } int main() { freopen("match.in","r",stdin); freopen("match.out","w",stdout); int n,i; scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%d",&A[i].x); A[i].cnt=i; } for(i=1;i<=n;i++) { scanf("%d",&B[i].x); B[i].cnt=i; } sort(A+1,A+1+n,cmp); sort(B+1,B+1+n,cmp); for(i=1;i<=n;i++) aa[A[i].cnt] = B[i].cnt; margef(1,n); printf("%d\n",ans%99999997); return 0; }my ac code:
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> #define maxn 100010 int n; int aa[maxn],T[maxn]; typedef struct{ int val,id; }node; node a[maxn],b[maxn]; int ans; bool cmp(node A,node B) { return A.val<B.val; } void marge(int l,int r) { if(l==r)return; int mid=(l+r)/2; marge(l,mid); marge(mid+1,r); int i=l,j=mid+1,k; for(k=l;k<=r;k++) { if((i<=mid)&&((j>r)||aa[i]<=aa[j]))T[k]=aa[i++]; else { T[k]=aa[j++]; ans+=mid-i+1; ans%=99999997; } } for(i=l;i<=r;i++)aa[i]=T[i]; } int main() { freopen("match.in","r",stdin); freopen("match.out","w",stdout); scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i].val); a[i].id=i; } for(int i=1;i<=n;i++) { scanf("%d",&b[i].val); b[i].id=i; } std::sort(a+1,a+1+n,cmp); std::sort(b+1,b+1+n,cmp); for(int i=1;i<=n;i++)aa[a[i].id]=b[i].id; marge(1,n); printf("%d\n",ans%99999997); return 0; }