CodeForces 540E - Infinite Inversions(离散化+BIT)
题目链接 https://cn.vjudge.net/problem/CodeForces-540E
【题意】
有一个无限长的序列,1,2,3,…n,n+1…,现在要将它们中的某些元素交换,问你交换后所得的序列中逆序对的总数是多少?
【输入格式】
第一行为整数n,代表要序列中要交换的位置,接下来n行,每行两个位置,ai,bi代表序列中处于ai和位置的元素发生一次交换(n<=1e5, ai,bi<=1e9)
【输出格式】
输出一个整数表示交换之后的序列中逆序对的个数
【思路】
逆序对的问题可以用BIT来解决,但是这道题的数据范围很大,于是想到离散化,因为最多只会把2e5个数字进行交换,所以我们只要把要交换的数记录下来,同时把连续的且不需要交换的数值缩成一个点,同时记录下这个点的权值,也就是这个点实际上代表多少个数,这样一来,区间最大为4e5,可以用BIT来求解逆序对的问题了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int maxn=100050;
int n;
int a[maxn],b[maxn];
vector<P> v;
int bit[maxn<<2],len;
int id[maxn<<2],w[maxn<<2];
ll sum(int i){
ll ans=0;
while(i>0){
ans+=bit[i];
i-=i&-i;
}
return ans;
}
void add(int i,int x){
while(i<=len){
bit[i]+=x;
i+=i&-i;
}
}
int main(){
scanf("%d",&n);
for(int i=0;i<n;++i) {
scanf("%d%d",&a[i],&b[i]);
v.push_back(P(a[i],1));
v.push_back(P(b[i],1));
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
int cnt=v.size();
for(int i=0;i<cnt-1;++i){
if(v[i].first+1<v[i+1].first){
v.push_back(P(v[i].first+1,v[i+1].first-v[i].first-1));
}
}
sort(v.begin(),v.end());
len=cnt=v.size();
for(int i=1;i<=cnt;++i){
id[i]=i;
w[i]=v[i-1].second;
}
for(int i=0;i<n;++i){
int p1=lower_bound(v.begin(),v.end(),P(a[i],0))-v.begin()+1;
int p2=lower_bound(v.begin(),v.end(),P(b[i],0))-v.begin()+1;
swap(id[p1],id[p2]);
}
ll ans=0;
for(int i=1;i<=cnt;++i){
ans+=w[i]*(sum(len)-sum(id[i]));
add(id[i],w[i]);
}
printf("%lld\n",ans);
return 0;
}