【題解】洛谷P2448: 無盡的生命

sad_lin發表於2024-11-21

P2448 無盡的生命

這題難的不是逆序對模板,主要是如何處理不會操作的數,我們交換操作的與不操作的數可以分割出區間,每個區間我們都當作一個獨立的個體。

image

這個圖就可以劃分出以下區間(起始編號,區間個數)(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;
}