HDU 4262 Juggler

点我看题

初步想法是模拟,找到下一个位置并记录操作数,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\n",ans);
74 
75     }
76     return 0;
77 }

 

posted @ 2016-10-22 01:11  BBBob  阅读(214)  评论(0编辑  收藏  举报