P2448 無盡的生命
這題難的不是逆序對模板,主要是如何處理不會操作的數,我們交換操作的與不操作的數可以分割出區間,每個區間我們都當作一個獨立的個體。
這個圖就可以劃分出以下區間(起始編號,區間個數)(1,1),(2,2),(4,1),(5,1),(6,1),(7,1)
此時我們對查詢交換區間進行離散化,對新的區間編號,再進行交換和逆序對操作,注意此時求逆序對個數需要乘上區間個數。
#include<bits/stdc++.h>
#define int long long
#define re register
const int N=1e6+10;
const int mod=998244353;
using namespace std;
int n;
int b[N],o=0;
int idx[N],idy[N];
int t[N],row[N];
int a[N],id[N];
int tree[N];
int len;
int lb(int x){
return x&-x;
}
void add(int x,int k){
while(x<=len){
tree[x]+=k;
x+=lb(x);
}
}
int query(int x){
int sum=0;
while(x){
sum+=tree[x];
x-=lb(x);
}
return sum;
}
signed main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin>>n;
for(int i=1;i<=n;i++){
int x,y;
cin>>x>>y;
idx[i]=x;
idy[i]=y;
b[++o]=x;
b[++o]=y;
}
sort(b+1,b+o+1);
int tot=unique(b+1,b+o+1)-b-1;
len=0;
row[++len]=b[1];
t[len]=1;
for(int i=2;i<=tot;i++){
if(b[i]-b[i-1]>1){
row[++len]=b[i-1]+1;
t[len]=b[i]-b[i-1]-1;
}
row[++len]=b[i];
t[len]=1;
}
for(int i=1;i<=len;i++){
id[i]=i;
}
for(int i=1;i<=n;i++){
int x=lower_bound(row+1,row+1+len,idx[i])-row;
int y=lower_bound(row+1,row+1+len,idy[i])-row;
swap(t[x],t[y]);
swap(id[x],id[y]);
}
int ans=0;
for(int i=len;i>=1;i--){
ans+=query(id[i]-1)*t[i];
add(id[i],t[i]);
}
cout<<ans;
return 0;
}