P1966 [NOIP2013 提高组] 火柴排队

一道很早做过的题

其实很好感性理解

第一个数列的第k大 对应 第二个数列的第k大

那么问题就变为 用最少的步数 交换两个相邻的数 使得两数列一一对应

这就是一道逆序对的模板题

#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) x&(-x)
#define ll long long
const int maxn=1e5+5;
const int mod=1e8-3;
int n,cnt,tot,ans; 
int tr[maxn],a[maxn],b[maxn],c[maxn],d[maxn],id[maxn],x[maxn];
map<int,int>mp1,mp2;
void upd(int xx,int val){
	while(xx<maxn)tr[xx]+=val,xx+=lowbit(xx);
}
int query(int xx){
	int res=0;
	while(xx)res+=tr[xx],xx-=lowbit(xx);
	return res; 
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++)cin>>a[i],c[i]=a[i];
    for(int i=1;i<=n;i++)cin>>b[i],d[i]=b[i];
    sort(c+1,c+1+n);
    sort(d+1,d+1+n);
    for(int i=1;i<=n;i++)
    mp1[c[i]]=++cnt;
    for(int i=1;i<=n;i++)
    mp2[d[i]]=++tot;
    for(int i=1;i<=n;i++)
    id[mp1[a[i]]]=i;
	for(int i=1;i<=n;i++)
	x[i]=id[mp2[b[i]]];
	upd(x[n],1);
	for(int i=n-1;i>=1;i--)
	ans=(ans+query(x[i]))%mod,upd(x[i],1);
	cout<<ans<<endl;
	return 0;
}
posted @ 2022-04-10 17:56  wzx_believer  阅读(78)  评论(0)    收藏  举报