题目链接:https://atcoder.jp/contests/abc396/tasks/abc396_f
题意:
给定一个序列A,构造m个序列B,其中第i个序列第j个值为Bj= (Aj + i-1) %m
询问每个Bj的逆序对数目
思路:
由于模了m,所以一开始的序列每个元素的大小在[0,m-1)
发现当元素都+1时,对于序列中元素大小为m-1的:(m-1 +1)%m =0 ,而其他小于m-1的增加1,也就是相对顺序不变
于是只关注m-1元素的变化对 逆序对数目 的影响
对于这些元素:
- 1 在它们之前的数,除了同类,其他数都比它们大,而变化前它们都比其他数大
- 2 在它们之后的数,除了同类,其他数都比它们大,而变化前它们都比其他数大
因此左半边多构成了逆序对,右半边少构成了逆序对
将这些影响加起来获得每个询问的答案
记得开ll
int n,m;
int a[maxn],b[maxn];
int res;void merge(int l,int r){if(l==r)return;int mid=l+r>>1;merge(l,mid);merge(mid+1,r);int i=l,j=mid+1,p=l;while(i<=mid&&j<=r){if(a[i]<=a[j]){b[p++]=a[i];i++;}else{b[p++]=a[j];j++;res+=mid+1-i;}}while(i<=mid){b[p++]=a[i++];}while(j<=r){b[p++]=a[j++];}for(int s=l;s<=r;s++){a[s]=b[s];}
}vector<int> arr[maxn];
void solve(){cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];a[i]%=m;arr[a[i]].pb(i);}merge(1,n);cout<<res<<endl;for(int k=1;k<=m-1;k++){for(int j=0;j<arr[m-k].size();j++){res+=arr[m-k][j]-1-j;res-=(n-arr[m-k][j]-(arr[m-k].size()-j-1));}cout<<res<<endl;}
}