CF540E 题解
思路
虽然值域很大,但是 不大。看个样例:
2
3 8
5 10
将点交换后,会发现对于 或 的数,不会产生逆序对。
同时,对于 , 会发现产生的逆序对是一样的。运用整体思想,把它们看成一个点,称为“区间点”。
对于需要修改的点,我们也看成一个点,至多有 个点,构成 个区间点。所以数组记得开到 。
因为求逆序对只在意数的相对大小,所以将每个点离散化。对于区间点,选其中的任意值离散化都相同。
注意:一个区间点实际上有区间点的长度个。
然后对所有的点求逆序对即可。
#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;
}

浙公网安备 33010602011771号