CF540E 题解

思路

虽然值域很大,但是 nn 不大。看个样例:

2
3 8
5 10

将点交换后,会发现对于 x<2x<2x>10x>10 的数,不会产生逆序对。

同时,对于 6,76,7, 会发现产生的逆序对是一样的。运用整体思想,把它们看成一个点,称为“区间点”。

对于需要修改的点,我们也看成一个点,至多有 2×1052\times 10^5 个点,构成 2×10512\times 10^5-1 个区间点。所以数组记得开到 4×1054\times 10^5

因为求逆序对只在意数的相对大小,所以将每个点离散化。对于区间点,选其中的任意值离散化都相同。

注意:一个区间点实际上有区间点的长度个。

然后对所有的点求逆序对即可。

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int N = 5e5+10;
int n,m;
struct BIT{
    int c[N],t[N];
    int tg,len=N;
    void clear() {tg++;}
    void init(int l) {len=l;}
    #define lowbit(x) ((x)&-(x))
    void upd(int x,int k) {for(;x<=len;x+=lowbit(x)) if(tg==t[x]) c[x]+=k; else c[x]=k, t[x]=tg;}
    int s(int x) {int p=0;for(;x;x-=lowbit(x)) if(tg==t[x]) p+=c[x]; return p;}
}c;
int p[N],cnt,x[N],y[N];
int a[N],t[N],rk[N];
signed main() {
	cin>>n;
	for(int i=1;i<=n;i++) {
		cin>>x[i]>>y[i];
		p[++cnt]=x[i],p[++cnt]=y[i];
	}
	sort(p+1,p+cnt+1);
	cnt=unique(p+1,p+cnt+1)-(p+1);
	int cc=1;
	a[cc]=p[1],t[cc]=1;
	for(int i=2;i<=cnt;i++) {
		if(p[i]-p[i-1]>1) {
			a[++cc]=p[i-1]+1;
			t[cc]=p[i]-p[i-1]-1;
		}
		a[++cc]=p[i],t[cc]=1;
	}
	#define xb(i) (lower_bound(a+1,a+cc+1,i)-a)
	for(int i=1;i<=cc;i++) {
		rk[i]=i;
	}
	for(int i=1;i<=n;i++) {
		int xx=xb(x[i]),yy=xb(y[i]);
		swap(t[xx],t[yy]);
		swap(rk[xx],rk[yy]);
	}
	c.init(cc);
	int ans=0;
	for(int i=cc;i>=1;i--) {
		ans+=c.s(rk[i]-1)*t[i];
		c.upd(rk[i],t[i]);
	}
	cout<<ans;
	return 0;
}
posted @ 2023-11-13 22:01  cjrqwq  阅读(11)  评论(0)    收藏  举报  来源