题意:
你有一个序列{a1,a2,...,an},然后你可以删除一个长度为m的连续子序列. 问如何删除才能使逆序对最少.
<span style="font-size:14px;">//#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<stdio.h>
#include<math.h>
#include <string>
#include<string.h>
#include<map>
#include<queue>
#include<set>
#include<utility>
#include<vector>
#include<algorithm>
#include<stdlib.h>
using namespace std;
#define eps 1e-8
#define pii pair<int,int>
#define inf 0x3f3f3f3f
#define rd(x) scanf("%d",&x)
#define rd2(x,y) scanf("%d%d",&x,&y)
#define ll long long int
#define mod 1000003
#define maxn 100005
#define maxm 5000005
int mi(int a,int b){return a<b?a:b;}
int ma(int a,int b){return a>b?a:b;}
int n,m,c1[maxn],c2[maxn],a[maxn];
int lowbit(int x){return x&(-x);}
void change1(int x,int d){
for(;x<=n;x+=lowbit(x)) c1[x]+=d;
}
void change2(int x,int d){
for(;x<=n;x+=lowbit(x)) c2[x]+=d;
}
int query1(int x){
int ans=0;
for(;x;x-=lowbit(x)) ans+=c1[x];
return ans;
}
int query2(int x){
int ans=0;
for(;x;x-=lowbit(x)) ans+=c2[x];
return ans;
}
int main()
{
int t;
rd(t);
while(t--){
rd2(n,m);
for(int i=1;i<=n;i++) rd(a[i]);
memset(c1,0,sizeof(c1));//c1记录后缀解
memset(c2,0,sizeof(c2));//c2记录前缀解
ll res=0;
for(int i=n;i>=m+1;i--){
res+=query1(a[i]-1);
change1(a[i],1);
}
ll cur=res;
for(int i=m+1;i<=n;i++){
cur-=query1(a[i]-1);
cur-=query2(n)-query2(a[i]);//删除a[i]点并去除贡献
change1(a[i],-1);
cur+=query1(a[i-m]-1);//添加a[i-m]点并添加贡献
cur+=query2(n)-query2(a[i-m]);
change2(a[i-m],1);
//res=mi(res,cur);
res=res<cur?res:cur;
}
printf("%I64d\n",res);
}
return 0;
}
</span>