一、内容

题意:给定一个连续的无限序列{1,2,3,4,5,6…},然后给出几个区间,将2端的值进行swap,最后求有多少个逆序对。

二、思路

  • 将题目要进行交换的点都保存下来,然后在把中间没有出现的区间离散化成一个点,权值是这段区间有几个数
    例如 1 2 5 9 就可以化成 1 2 3 4 5 6 . 3代表【3,4】权值为2,5代表【6,7,8】权值为3。

  • 然后用一个vecotr保存这些离散化后的点,vector里面存一个pair,pair的first代表这个点的值是多少,second代表有多少个数,5所代表的【6,7,8】 所以second保存的是3,first保存的是6。

  • 最后模拟一下端点交换,用一个id数组存储离散化后的各个数在树状数组中的序号,然后二分在vector中查找位置进行交换,最后id数组保存的就是交换后的位置,然后逆序求一下逆序对就可以了

三、代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define X first
#define Y second
#define P pair<int ,int>
using namespace std;
const int maxn = 1e5 + 5;
struct {
	int l, r;	
}itval[maxn];
vector<P> pa;//第一个值保存这个区间代表的点 第二个值保存权值(就是有几个数) 
int w[maxn << 2];//保存每个点代表有多少个数
int id[maxn << 2]; //保存交换后的数在树状数组上的id 
int c[maxn << 2]; //树状数组 
int n, cnt;
void update(int x, int v) {
	for (int i = x; i <= cnt; i += i & (-i)) {
		c[i] += v; 
	}
}
long long query(int x) {
	long long ans = 0;
	for (int i = x; i > 0; i -= i & (-i)) {
		ans += c[i];
	}
	return ans;
}
void swap(int &a, int &b) {
	int tem = a;
	a = b;
	b = tem;
} 
int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) {
		scanf("%d%d", &itval[i].l, &itval[i].r);
	 	pa.push_back(P(itval[i].l, 1));
	 	pa.push_back(P(itval[i].r, 1)) ;
	}
	//离散化 
	sort(pa.begin(), pa.end());
	//去重 
	pa.erase(unique(pa.begin(), pa.end()), pa.end());
	cnt = pa.size();
	//将中间的区间化成一个点 保存这段区间有多少个数 
	for (int i = 1; i < cnt; i++) {
		if (pa[i].X > pa[i - 1].X + 1) { //这个数组用来二分查找进行位置的查询 
			int x = pa[i - 1].X + 1;
			int y =  pa[i].X - pa[i - 1].X - 1; 
			pa.push_back(P(x, y));
		}
	}
	//再次离散化 
	sort(pa.begin(), pa.end());
	cnt = pa.size();
	//用w,num来进行模拟交换
	for (int i = 0; i < cnt; i++) {
		w[i + 1] = pa[i].Y;
		id[i + 1] = i + 1; 
	} 
	//模拟交换 
	for (int i = 1; i <= n; i++) {
		int xx = lower_bound(pa.begin(), pa.end(), P(itval[i].l,0)) - pa.begin() + 1; //必须加1才是第几个 
		int yy = lower_bound(pa.begin(), pa.end(), P(itval[i].r,0)) - pa.begin() + 1;
		swap(id[xx], id[yy]);
	}
	long long ans = 0;
	//求逆序对
	for (int i = cnt; i > 0; i--) {
		ans += query(id[i]) * w[id[i]];
		update(id[i], w[id[i]]);
	} 
	printf("%I64d\n\n", ans);
	return 0;
}