Luogu P2448 无尽的生命 题解

双倍经验:CF540E

题意简述

给定一个数列 \(1,2,3\dots n\)\(k\) 次操作,每次操作交换数列中下标为 \(x\)\(y\) 的数。求最终数列中有多少个逆序对。其中 $ n,x,y\le 2^{31}-1, k\le 10^5 $。

前置知识

树状数组,离散化

Solution

显然可以用树状数组求逆序对。但是难点在于原数列中可能有很多元素没有被交换过,要考虑怎么计算它们的贡献。

注意到操作数 \(k\le10^5\),因此最多只有 \(2\times10^5\) 个数被交换了。这样,最多会产生 \(2\times10^5-1\) 个区间,处于这些区间之间的数都没有被交换过。设区间 \([l,r]\) 中的所有元素都没有被交换过,显然这些数两两之间都不可能产生逆序对,因此考虑用任意一个 \(x\in[l,r]\) 代替这些数,并将 \(x\) 的权值设为 \(r-l+1\) 。对于交换过的数,权值设为 \(1\) 即可。这样一来,我们就得到了一个新的序列,这个序列仅有不超过 \(4\times10^5-1\) 个数,离散化之后就可以使用权值树状数组来求逆序对了。注意对于每个 \(x\) 统计贡献时要乘上 \(x\) 的权值。

时间复杂度 \(O(k \log{k})\)

Code

#include<bits/stdc++.h>
#define int long long
#define lowbit(x) x&-x
#define INF 0x7fffffff
using namespace std;
const int N=1e6+10;
struct node{int x,y;}t[N];
int n;
int a[N],b[N],c[N];
void add(int x,int k) {while(x<=n) c[x]+=k,x+=lowbit(x);}
int get_sum(int x) {int res=0;while(x>=1) res+=c[x],x-=lowbit(x);return res;}
int s[N],siz[N];//siz[x]表示x的权值
signed main()
{
	int k;
	scanf("%lld",&k);
	for(int i=1;i<=k;i++) 
		scanf("%lld%lld",&t[i].x,&t[i].y),
		a[i*2-1]=t[i].x,a[i*2]=t[i].y;
	memcpy(b,a,sizeof(b));
	sort(b+1,b+2*k+1);
	n=unique(b+1,b+2*k+1)-b-1;
	for(int i=1;i<=n;i++) a[i*2-1]=b[i];
	n=n*2-1;
	for(int i=1;i<=n;i++) 
	{
		if(i&1) continue;
		if(a[i+1]==a[i-1]+1) a[i]=INF;
		else a[i]=a[i-1]+1,s[i]=a[i+1]-a[i-1]-1;
	}
	memcpy(b,a,sizeof(b));
	sort(a+1,a+n+1);
	int tmp=n;
	while(a[n]==INF) n--;
	for(int i=1;i<=tmp;i++)
	{
		if(b[i]==INF) continue;
		int idx=lower_bound(a+1,a+n+1,b[i])-a;
		siz[idx]=s[i];
	}
	for(int i=1;i<=n;i++) if(!siz[i]) siz[i]=1;
	memcpy(b,a,sizeof(b));
	for(int i=1;i<=k;i++)
	{
		int idx=lower_bound(b+1,b+n+1,t[i].x)-b;
		int idy=lower_bound(b+1,b+n+1,t[i].y)-b;
		swap(a[idx],a[idy]);
	}
	int ans=0;
	for(int i=n;i>=1;i--)
	{
		int idx=lower_bound(b+1,b+n+1,a[i])-b;
		ans+=siz[i]*get_sum(idx-1);
		add(idx,siz[i]);
	}
	printf("%lld\n",ans);
	return 0;
}
posted @   __Star_Sky  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示