1. 程式人生 > 實用技巧 >E.Divide Square(樹狀陣列/線段樹)(掃描線)

E.Divide Square(樹狀陣列/線段樹)(掃描線)

讓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;
}