Inversion
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 752 Accepted Submission(s): 210
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
Recommend
解析:删除一段,即将原区间分为三个部分,即为(A,B,C),其中B为删除的一段。
每一次枚举,先将B最左端的 x 加入A,逆序数增加:A中比x大的数量+C中比x小的数量;然后将C最左端的 y 加入B,那么逆序数减少的数量就为:A中比 y 大的数量+C中比 y 小的数量。
用树状数组维护A与B即可。
代码:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<algorithm>
#define ms0(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long LL;
const int maxn=1e5;
int n,m;
int a[maxn+10],cl[maxn+10],cr[maxn+10];
int getin()
{
int ans=0;char tmp;
while(!isdigit(tmp=getchar()));
do ans=(ans<<3)+(ans<<1)+tmp-'0';
while(isdigit(tmp=getchar()));
return ans;
}
int sum(int p[],int x)
{
LL ans=0;
while(x)
{
ans+=p[x];
x-=x&(-x);
}
return ans;
}
void add(int p[],int x,int y)
{
for(;x<=n;x+=x&(-x))p[x]+=y;
}
int main()
{
freopen("1.in","r",stdin);
int t,i; LL now,ans;
for(t=getin();t;t--)
{
ms0(cl),ms0(cr);
n=getin(),m=getin();
for(i=1;i<=n;i++)a[i]=getin();
for(now=0,i=n;i>m;i--)
{
now+=sum(cr,a[i]-1);
add(cr,a[i],1);
}
for(ans=now,i=1;i<=n-m;i++)
{
now+=sum(cl,n)-sum(cl,a[i])+sum(cr,a[i]-1);
add(cl,a[i],1);
now-=sum(cl,n)-sum(cl,a[i+m])+sum(cr,a[i+m]-1);
add(cr,a[i+m],-1);
ans=min(ans,now);
}
printf("%I64d\n",ans);
}
return 0;
}