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;
}
posted @ 2020-08-26 20:16  Simex  阅读(75)  评论(0编辑  收藏  举报