Infinite Inversions CodeForces - 540E题目
There is an infinite sequence consisting of all positive integers in the increasing order: p = {1, 2, 3, …}. We performed n swap operations with this sequence. A swap(a, b) is an operation of swapping the elements of the sequence on positions a and b. Your task is to find the number of inversions in the resulting sequence, i.e. the number of such index pairs (i, j), that i < j and pi > pj.
Input
The first line contains a single integer n (1 ≤ n ≤ 105) — the number of swap operations applied to the sequence.
Each of the next n lines contains two integers ai and bi (1 ≤ ai, bi ≤ 109, ai ≠ bi) — the arguments of the swap operation.
Output
Print a single integer — the number of inversions in the resulting sequence.
Examples
Input
2
4 2
1 4
Output
4
Input
3
1 6
3 4
2 5
Output
15
题目网址
链接: https://codeforces.com/problemset/problem/540/E.
想法
总体的想法:
1.将输入的L R放入一个数组并且排序,去重。
2.根据形成的数组,将每个query的LR修改为形成数组的下表。
3.声明一个新的数组tmp,并且按照修改后query的L ,R来实现交换,并形成一个结果数组1。
4.便利结果数组1,并且将他放入结果数组2中(由于结果数组1是交换后的,所以将pos中交换的间隔放入结果数组2中)
5.使用树状数组计算逆序对数量。
其实就是离散化+额外计算一下中间为参与交换的部分。只不过想起来会比较绕
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 1e5 + 1e3;
typedef long long int LL;
struct Node{
int l , r;
}query[N];//询问数组
struct Node1{
int pos;
LL val;
}res[N<<2];//结果数组2
int n , pos[N<<1] , tmp[N<<1] , m;//pos为第二步形成的数组,tmp为结果数组1
LL cnum[N<<2];//树状数组使用的数组,由于原本L~R为N,所以L,R加起来最多为2N,
//再计算一下中间部分,最多为4*N
int lowbit(int x){
return x&(-x);
}
LL getSum(int index){
LL res = 0;
for(int i = index ; i > 0 ; i -= lowbit(i) ){
res += cnum[i];
}
return res;
}
void add(int index , int num){
for(int i = index ; i <= m ; i += lowbit(i)){
cnum[i] += num;
}
}
int main(){
ios::sync_with_stdio(false);
int i , j ;
cin>>n;
for(i = 1 , j = 0 ; i <= n ; i ++ ){
cin>>query[i].l>>query[i].r;
pos[++j] = query[i].l;pos[++j] = query[i].r;
}
sort(pos+1,pos+1+j);
int len = unique(pos+1,pos+1+j)-pos-1;
for(i = 1 ; i <= n ; i ++ ){
query[i].l = lower_bound(pos+1,pos+1+len,query[i].l)-pos;
query[i].r = lower_bound(pos+1,pos+1+len,query[i].r)-pos;
}
for(i = 1 ; i <= len ; i ++ ) tmp[i] = i;
for(i = 1 ; i <= n ; i ++ ){
swap(tmp[query[i].l],tmp[query[i].r]);
}
int tot = 0;
for(i = 1 ; i <= len ; i ++ ){
if(pos[i-1]+1<=pos[i]-1){
++tot;
res[tot].pos = i*2-1;
res[tot].val = (LL)(pos[i]-pos[i-1]-1);
}
++tot;
res[tot].pos = tmp[i]*2;
res[tot].val = 1;
}
m = len*2;
LL reser = 0;
for(i = 1 ; i <= tot ; i ++ ){
reser += (getSum(m)-getSum(res[i].pos))*res[i].val;
add(res[i].pos , res[i].val);
}
cout<<reser<<endl;
return 0;
}