标签:
题目链接:
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1087 Accepted Submission(s): 323
有一个序列,然后你可以删除一个长度为mm的连续子序列. 问如何删除才能使逆序对最少.
思路:
也是套路,逆序对可以用树状数组求得,连续的可以使用滑动窗口,跟尺取法差不多啦;开了两个树状数组一个记录左边界之前的数,一个记录右边界后面的数,然后更新逆序对的数目,取最小就好了;
AC代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn=1e5+10; int sum1[maxn],sum2[maxn],n,m,a[maxn]; int lowbit(int x){return x&(-x);} inline void update1(int x,int num) { while(x<=n) { sum1[x]+=num; x+=lowbit(x); } } inline int query1(int x) { int s=0; while(x) { s+=sum1[x]; x-=lowbit(x); } return s; } inline void update2(int x,int num) { while(x<=n) { sum2[x]+=num; x+=lowbit(x); } } inline int query2(int x) { int s=0; while(x) { s+=sum2[x]; x-=lowbit(x); } return s; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); for(int i=0;i<=n;i++)sum1[i]=sum2[i]=0; for(int i=1;i<=n;i++)scanf("%d",&a[i]); LL su=0; for(int i=n;i>0;i--) { su=su+query2(a[i]-1); update2(a[i],1); } LL ans=su,temp=su;int l,r=1; for(l=1;l<=n-m+1;l++) { while(r-l<m&&r<=n) { update2(a[r],-1); temp=temp-query2(a[r]-1); temp=temp-(l-1-query1(a[r])); r++; } ans=min(ans,temp); temp=temp+(l-1-query1(a[l])); temp=temp+query2(a[l]-1); update1(a[l],1); } printf("%lld\n",ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/zhangchengc919/p/5922283.html