[noip2013]火柴排队

涵涵有两盒火柴,每盒装有 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)

#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;
}
View Code

 新版本:

#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)

#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;
}
View Code

主要是第一个版本映射写的太辣鸡了点;

posted @ 2016-10-09 21:20  CHADLZX  阅读(129)  评论(0编辑  收藏  举报