P1966 火柴排队
让A,b序列中大小排名相对应即可
若A中第j大的位于i,则应该b中第j大位于i
证明:假如a1<a2,b1<b2
则排列方式有 a1,a2,b1,b2或 a1,a2,b2,b1那么
对于这两种情况上,平方并做差,即可得以上结论
然而大问题是这样离散化后怎么搞出交换几次呢
离散化后
\(c_{a_i}\)=\(b_i\),然后若我们最后拍完序
定然\(c_i\)=i
也就是记录了相同排名的值得对应关系
结果是要让他们一一对应的
也就是上面的
拍完序后,然后就是相同位置对应了
其实也就是记录了A中第i大的元素的位置和b中的对应位置
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int tree[100001];
struct num{
int v;
int p;
}a[100001],b[100001];
int n;
const int mod = 99999997;
int a1[100001];
int b1[100001];
int c[100001];
int q[100001];
bool cmp(num x,num y){
return x.v<y.v;
}
int lowbit(int x){
return x&-x;
}
void up(int x,int y){
while(x<=n){
tree[x]+=y;
tree[x]%=mod;
x+=lowbit(x);
}
}
int find(int x){
int ans=0;
while(x>=1){
ans+=tree[x];
ans%=mod;
x-=lowbit(x);
}
return ans;
}
int ans;
bool cmp1(const int &x,const int &y){
return q[x]>q[y];
}
int main (){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i].v);
a[i].p=i;
}
for(int i=1;i<=n;++i){
scanf("%d",&b[i].v);
b[i].p=i;
}
sort(a+1,a+1+n,cmp);
sort(b+1,b+1+n,cmp);
for(int i=1;i<=n;++i){
q[a[i].p]=b[i].p;
}
for(int i=n;i>=1;--i){
up(q[i],1);
ans+=find(q[i]-1)%mod;
ans%=mod;
}
cout<<(ans%mod+mod)%mod;
return 0;
}