初步想法是模拟,找到下一个位置并记录操作数,O(n^2)肯定会超时。
那么进行优化,会发现到下一位置的操作数就是两个位置之间存在的数的个数,于是就变成了计数问题。
不难想到用树状数组或线段树进行计数,时间复杂度O(nlogn)。
1 #include<cstdio> 2 #include<algorithm> 3 #include<vector> 4 #include<queue> 5 #include<string.h> 6 using namespace std; 7 const int Nmax=100005; 8 int n,now; 9 long long ans; 10 int num[Nmax],pos[Nmax]; 11 int c[Nmax]; 12 13 int lowbit(int x) 14 { 15 return x&(-x); 16 } 17 18 int get_sum(int x) 19 { 20 int ans=0; 21 while(x) 22 ans+=c[x],x-=lowbit(x); 23 return ans; 24 } 25 26 int query(int l,int r) 27 { 28 return get_sum(r)-get_sum(l-1); 29 } 30 31 void update(int p,int add) 32 { 33 while(p<=n) 34 c[p]+=add,p+=lowbit(p); 35 } 36 37 void build() 38 { 39 for(int i=0;i<=n;i++) 40 c[i]=0; 41 for(int i=1;i<=n;i++) 42 update(i,1); 43 } 44 45 int main() 46 { 47 freopen("in.in","r",stdin); 48 while(scanf("%d",&n) && n!=0) 49 { 50 for(int i=1;i<=n;i++) 51 { 52 scanf("%d",&num[i]); 53 pos[num[i]]=i; 54 } 55 build(); 56 now=1,ans=0; 57 for(int i=1;i<=n;i++) 58 { 59 if(pos[i]>now) 60 ans+=min(query(now,pos[i]),query(1,now)+query(pos[i],n)); 61 62 else if(pos[i]<now) 63 ans+=min(query(pos[i],now),query(now,n)+query(1,pos[i])); 64 else 65 ans++; 66 67 now=pos[i],update(pos[i],-1),num[pos[i]]=0; 68 if(i==n) 69 break; 70 while(!num[now]) 71 now=now%n+1; 72 } 73 printf("%lld ",ans); 74 75 } 76 return 0; 77 }