Inversion
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 246 Accepted Submission(s): 70
Problem Description
You have a sequence
{a1,a2,...,an}
and you can delete a contiguous subsequence of length
m
. So what is the minimum number of inversions after the deletion.
Input
There are multiple test cases. The first line of input contains an integer
T
, indicating the number of test cases. For each test case:
The first line contains two integers n,m(1≤n≤105,1≤m<n) - the length of the seuqence. The second line contains n integers a1,a2,...,an(1≤ai≤n) .
The sum of n in the test cases will not exceed 2×106 .
The first line contains two integers n,m(1≤n≤105,1≤m<n) - the length of the seuqence. The second line contains n integers a1,a2,...,an(1≤ai≤n) .
The sum of n in the test cases will not exceed 2×106 .
Output
For each test case, output the minimum number of inversions.
Sample Input
2 3 1 1 2 3 4 2 4 1 3 2
Sample Output
0 1
Source
求去掉一个长度为m的连续序列,使得剩下的序列,逆序对最少。
求出原序列的逆序对。
枚举每一个删除的区间[l,r]:
此时得到的逆序对的个数 = 总逆序对个数 - sum(对于每个在[l,r]区间的数x,比x大且在x前面的数的个数)
- sum(对于每个在[l,r]区间的数y,比y大且在y后面的数的个数) + sum(对于每个在区间[l,r]的数字z,比z大且在z前面但是也属于区间[l,r]的的数的个数)
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
#define maxn 100007
int tree[maxn];
#define ll long long
void add(int p,int q){
while(p > 0){
tree[p]+=q;
p-=p&-p;
}
}
int query(int p){
int ans = 0;
while(p < maxn){
ans += tree[p];
p += p&-p;
}
return ans;
}
ll lef[maxn],rig[maxn],que[maxn];
int p[maxn];
int main(){
int t,n,m;
scanf("%d",&t);
memset(tree,0,sizeof(tree));
lef[0] = rig[0] = que[0] = 0;
while(t--){
scanf("%d%d",&n,&m);
for(int i = 1;i <= n ;i++){
scanf("%d",&p[i]);
}
ll ans = 0;
for(int i = 1;i <= n; i++){
lef[i] = query(p[i]+1);
ans += lef[i];
add(p[i],1);
}
for(int i = 1;i <= n; i++)
add(p[i],-1);
for(int i = n;i >= 1; i--){
rig[i] = n-i-query(p[i]);
add(p[i],1);
}
for(int i = 1;i <= n; i++)
add(p[i],-1);
ll res = ans,w=0;
for(int i = 1;i <= n; i++)
rig[i] += rig[i-1], lef[i] += lef[i-1];
for(int i = 1;i <= n; i++){
if(i > m) {
add(p[i-m],-1);
w -= m - 1 - query(p[i-m]);
}
w += query(p[i]+1);
add(p[i],1);
res = min(res,ans-rig[i]+rig[i-m]-lef[i]+lef[i-m]+w);
}
for(int i = n-m+1;i <= n; i++)
add(p[i],-1);
printf("%lld\n",res);
}
return 0;
}