涵涵有两盒火柴,每盒装有 n 根火柴,每根火柴都有一个高度。现在将每盒中的火柴各自排成一列,同一列火柴的高度互不相同,两列火柴之间的距离定义为:
,其中 ai 表示第一列火柴中第 i 个火柴的高度,bi 表示第二列火柴中第 i 个火柴的高度。
每列火柴中相邻两根火柴的位置都可以交换,请你通过交换使得两列火柴之间的距离最小。请问得到这个最小的距离,最少需要交换多少次?如果这个数字太大,请输出这个最小交换次数对 99,999,997 取模的结果。
题解:
用"显然"证明法可知,当ai与bi在A和B中的rank相等时,S最小;
于是我们就可以把a数组映射成有序的,再把b数组按照a数组的映射方法映射,这样就可以按逆序对来做;
求逆序对还是按归并排序来做吧,树状数组做法虽然简洁,但需要离散;
代码:
老版本:
#01: Accepted (15ms, 67624KB)
#02: Accepted (15ms, 67624KB)
#03: Accepted (15ms, 67624KB)
#04: Accepted (15ms, 67624KB)
#05: Accepted (15ms, 67624KB)
#06: Accepted (31ms, 67624KB)
#07: Accepted (15ms, 67624KB)
#08: Accepted (31ms, 67624KB)
#09: Accepted (62ms, 67624KB)
#10: Accepted (125ms, 67624KB)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<algorithm> #include<iomanip> #include<map> #include<set> #include<vector> #include<ctime> #include<cmath> #define LL long long using namespace std; #define LL long long #define up(i,j,n) for(int i=(j);(i)<=(n);(i)++) #define max(x,y) ((x)<(y)?(y):(x)) #define min(x,y) ((x)<(y)?(x):(y)) #define FILE "1" const int maxn=101000,mod=99999997; int n; int a[maxn],b[maxn],q[maxn],c[maxn]; int read(){ bool flag=0;char ch=getchar();int x=0; while(ch>'9'||ch<'0'){if(ch=='-')flag=1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return flag?-x:x; } int d[maxn]; int lowbit(int x){return x&-x;} void add(int x){while(x<=n){d[x]+=1;x+=lowbit(x);}} LL get(int x){LL ans=0;while(x>0)ans=(ans+d[x])%mod,x-=lowbit(x);return ans;} void getni(){ LL ans=0; up(i,1,n){ ans=(ans+get(n+1-c[i]))%mod; add(n+1-c[i]); } printf("%I64d\n",ans); } const int step=7,tail=4000000,head=0; struct hash{ pair<int,int> t[5000000]; int find(int x,int d){ int y=x%mod*3%mod*5%tail; while(t[y].first!=x&&t[y].first!=0){ y+=step; if(y>tail)y-=tail; } if(t[y].first==0){ t[y].second=d; t[y].first=x; return y; } else return t[y].second; } }t,p;//手写map,用hash实现map的部分功能 int k[maxn]; void init(){ scanf("%d",&n); up(i,1,n)q[i]=a[i]=read(),t.find(a[i],i); up(i,1,n)k[i]=b[i]=read(); sort(q+1,q+n+1); sort(k+1,k+n+1); up(i,1,n)p.find(k[i],i); up(i,1,n)c[t.find(q[p.find(b[i],0)],0)]=i; getni(); } int main(){ init(); return 0; }
新版本:
#01: Accepted (0ms, 5000KB)
#02: Accepted (0ms, 5000KB)
#03: Accepted (0ms, 5000KB)
#04: Accepted (0ms, 5000KB)
#05: Accepted (0ms, 5000KB)
#06: Accepted (0ms, 5000KB)
#07: Accepted (0ms, 5000KB)
#08: Accepted (15ms, 5000KB)
#09: Accepted (31ms, 5000KB)
#10: Accepted (46ms, 5000KB)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<iostream> #include<cstring> #include<cstdio> #include<cstdlib> #include<algorithm> #include<iomanip> #include<map> #include<set> #include<vector> #include<ctime> #include<cmath> #define LL long long using namespace std; #define LL long long #define up(i,j,n) for(int i=(j);(i)<=(n);(i)++) #define max(x,y) ((x)<(y)?(y):(x)) #define min(x,y) ((x)<(y)?(x):(y)) #define FILE "1" const int maxn=101000,mod=99999997; int n,c[maxn]; struct node{ int num,id; bool operator<(const node& b)const{return num<b.num;} }a[maxn],b[maxn]; int read(){ bool flag=0;char ch=getchar();int x=0; while(ch>'9'||ch<'0'){if(ch=='-')flag=1;ch=getchar();} while(ch<='9'&&ch>='0'){x=x*10+ch-'0';ch=getchar();} return flag?-x:x; } int d[maxn]; int lowbit(int x){return x&-x;} void add(int x){while(x<=n){d[x]+=1;x+=lowbit(x);}} LL get(int x){LL ans=0;while(x>0)ans=(ans+d[x])%mod,x-=lowbit(x);return ans;} void getni(){ LL ans=0; up(i,1,n){ ans=(ans+get(n+1-c[i]))%mod; add(n+1-c[i]); } printf("%I64d\n",ans); } void init(){ scanf("%d",&n); up(i,1,n)a[i].num=read(),a[i].id=i; up(i,1,n)b[i].num=read(),b[i].id=i; sort(a+1,a+n+1);sort(b+1,b+n+1); up(i,1,n)c[a[i].id]=b[i].id; getni(); } int main(){ init(); return 0; }
主要是第一个版本映射写的太辣鸡了点;