【题解】洛谷P2448: 无尽的生命

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;
}
posted @ 2024-11-21 07:50  sad_lin  阅读(2)  评论(0编辑  收藏  举报