[NOIP2013 提高组] 火柴排队
可以证明a中第k大应该对于b中第k大
满足此条件的两个数列,完成一次交换,有可能使得答案变劣
只对一个数列进行操作和对两个数列进行操作是等价的
数据很大,需要离散化
假设确定a数组,只移动b,你会发现很困难
这里不妨使得a数组的第一项为第一,第二项为第二……
对应的b数组中的数也进行替换
就会变成一个求逆序对的问题
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <map>
using namespace std;
#define MAXN 100005
#define MOD (100000000-3)
map <int,int> mpa,mpb;
int tota = 0,totb = 0;
int a[MAXN],b[MAXN],t[MAXN];
int index[MAXN];
int N;
struct Binary {
#define lowbit(x) (x&(-x))
int pre[MAXN];
inline int query(int x) {
int ans = 0;
for(;x>0;x-=lowbit(x)) ans += pre[x];
return ans;
}
inline void update(int x,int c) {
for(;x<=N;x+=lowbit(x)) pre[x] += c;
}
} tr;
int main() {
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> N;
for(int i=1;i<=N;++i) {
cin >> a[i]; t[i] = a[i];
}
sort(t+1,t+1+N);
mpa[t[1]] = ++tota;
for(int i=2;i<=N;++i)
if(t[i]!=t[i-1]) mpa[t[i]] = ++tota;
for(int i=1;i<=N;++i) {
a[i] = mpa[a[i]];
if(index[a[i]]==0) index[a[i]] = i;
}
for(int i=1;i<=N;++i) {
cin >> b[i]; t[i] = b[i];
}
sort(t+1,t+1+N);
mpb[t[1]] = ++totb;
for(int i=2;i<=N;++i)
if(t[i]!=t[i-1]) mpb[t[i]] = ++totb;
for(int i=1;i<=N;++i) {
b[i] = mpb[b[i]]; b[i] = index[b[i]];
}
long long ans = 0;
for(int i=1;i<=N;++i) {
ans += tr.query(N) - tr.query(b[i]);
ans %= MOD;
tr.update(b[i],1);
}
cout << ans;
return 0;
}