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
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int maxn=100050;

int n;
int a[maxn],b[maxn];
vector

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;iscanf("%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;i1;++i){ if(v[i].first+11].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;iint 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; }

你可能感兴趣的:(CodeForces 540E - Infinite Inversions(离散化+BIT))