题目:
每 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;
}