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;
}
posted @ 2018-04-14 13:07  不想吃WA的咸鱼  阅读(131)  评论(0编辑  收藏  举报