题解:CF1830E Bully Sort

题目:

每 bully swap \(i,j\) 会使得 \(\sum_i \left | i-p_i \right |\) 减少 \((2j-2i)\),使得逆序对数减少 \((2j-2i-1)\)
又因为一个数始终单向移动,所以 bully swap 次数为 \((\sum_i \left | i-p_i \right | - 逆序对数)\)

代码:

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int QAQ=5e5+7;
int n,q,p[QAQ],cnt;
ll da[QAQ],ans[QAQ],ans1;
struct xxx {int a,b,c,cnt;} d[QAQ*6];
int s[QAQ];
#define lbd(x) (x&(-x))
void jia(int x,int c)
{
	for(int i=x;i<=n;i+=lbd(i)) s[i]+=c;
}
int cha(int x)
{
	int da=0;
	for(int i=x;i;i-=lbd(i)) da+=s[i];
	return da;
}
bool cmp1(xxx a,xxx b) {return a.b<b.b;}
void cdq(int l,int r)
{
	if(l==r) return ;
	int mid=(l+r)>>1,i=l;
	cdq(l,mid),cdq(mid+1,r),
	sort(d+l,d+mid+1,cmp1),sort(d+mid+1,d+r+1,cmp1);
	for(int j=mid+1;j<=r;j++)
	{
		while(i<=mid&&d[i].b<=d[j].b) jia(d[i].c,d[i].cnt),i++;
		ans[d[j].a]+=(ll)d[j].cnt*(cha(n)-cha(d[j].c));
	}
	for(int k=l;k<i;k++) jia(d[k].c,-d[k].cnt);
	i=mid;
	for(int j=r;j>=mid+1;j--)
	{
		while(i>=l&&d[i].b>=d[j].b) jia(d[i].c,d[i].cnt),i--;
		ans[d[j].a]+=(ll)d[j].cnt*cha(d[j].c-1);
	}
	for(int k=mid;k>i;k--) jia(d[k].c,-d[k].cnt);
}
signed main()
{
	cin>>n>>q;
	for(int i=1;i<=n;i++) cin>>p[i],ans1+=abs(i-p[i]),d[++cnt]={0,i,p[i],1};
	for(int i=1,x,y;i<=q;i++)
		cin>>x>>y,
		d[++cnt]={i,x,p[x],-1},d[++cnt]={i,y,p[y],-1},
		ans1-=abs(x-p[x]),ans1-=abs(y-p[y]),
		swap(p[x],p[y]),
		d[++cnt]={i,x,p[x],1},d[++cnt]={i,y,p[y],1},
		ans1+=abs(x-p[x]),ans1+=abs(y-p[y]),
		da[i]=ans1;
	cdq(1,cnt);
	for(int i=1;i<=q;i++) ans[i]+=ans[i-1];
	for(int i=1;i<=q;i++) cout<<da[i]-ans[i]<<'\n';
	return 0;
}
posted @ 2025-10-14 15:10  _a1a2a3a4a5  阅读(7)  评论(1)    收藏  举报