标签:
Time Limit: 3000MS | Memory Limit: 65536KB | 64bit IO Format: %I64d & %I64u |
Description
Input
Output
Sample Input
Sample Output
Source
滑动区间扫描。用树状数组来维护逆序对的个数(数组存储数n是否已经出现,通过计算数组前缀和来求逆序对,思路和比这篇早些写的POJ2182 Lost Cows类似)
维护L([i])树状数组表示i左边比a[i]的数的数量,R([i])树状数组表示i右边比a[i]小的数的数量。窗口从左滑到右面,不断更新L和R,计算答案并更新
1 /*by SilverN*/ 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cstdio> 6 #include<cmath> 7 using namespace std; 8 const int mxn=110000; 9 int n,m; 10 struct tree{ 11 int a[mxn]; 12 inline lowbit(int x){return x&-x;} 13 void init(){memset(a,0,sizeof a);} 14 void add(int x,int num){ 15 while(x<=n){ 16 a[x]+=num; 17 x+=lowbit(x); 18 } 19 return; 20 } 21 int sum(int x){ 22 int res=0; 23 while(x){ 24 res+=a[x]; 25 x-=lowbit(x); 26 } 27 return res; 28 } 29 }; 30 int a[mxn]; 31 tree Le,Ri; 32 int main(){ 33 int T; 34 scanf("%d",&T); 35 while(T--){ 36 scanf("%d%d",&n,&m); 37 int i,j; 38 for(i=1;i<=n;i++){ 39 scanf("%d",&a[i]); 40 } 41 Le.init(); 42 Ri.init(); 43 long long ans; 44 long long tmp=0; 45 //求原有逆序对数(最左边滑动窗口内的不算) 46 for(i=n;i>m;i--){ 47 Ri.add(a[i],1); 48 tmp+=Ri.sum(a[i]-1); 49 } 50 ans=tmp; 51 //finish 52 for(i=1;i<=n-m;i++){ 53 Ri.add(a[i+m],-1);//窗口滑动,窗口最右面的数被删除 54 tmp=tmp+Ri.sum(a[i]-1)-Ri.sum(a[i+m]-1); 55 tmp=tmp+Le.sum(n+1-(a[i]+1))-Le.sum(n+1-(a[i+m]+1)); 56 Le.add(n+1-a[i],1); 57 ans=min(ans,tmp); 58 } 59 printf("%lld\n",ans); 60 } 61 return 0; 62 }
标签:
原文地址:http://www.cnblogs.com/SilverNebula/p/5648291.html