CF830B:Cards Sorting

对叠放着的n张牌,第i张牌写有数字Ai,进行操作:将牌堆顶的牌取出,若是当前牌堆最小值就扔掉,否则放到牌堆底,求牌堆空时操作次数。

怎么看怎么像约瑟夫。。不过约瑟夫DP我不太熟,于是就yy了一下

“当前最小值”??优先队列。把Ai和i绑起来扔到优先队列里,就可以知道下一步要跳到哪里。

有个问题:如果有多个Ai怎么办???把这些相同的数字列出来,下标升序排列,假如上一次抽完牌的位置是now,那么它在把所有这些相同的数字取完后,会走到“离now最近的第一个比now小的下标”那里

因此优先队列中以数字大小为第一关键字而位置为第二,每次取出相同数字的所有位置,利用单调性边取边直接判断我们要找的“离now最近的第一个比now小的下标”(然而代码中我傻了,拿下标出来二分查找)

这样统计答案还有个小问题:有些牌已经被抽掉了,所以用下标统计答案是不行滴!那就加个树状数组吧,复杂度O(nlog2n)

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<algorithm>
 4 #include<cstdlib>
 5 #include<cstring>
 6 #include<queue>
 7 //#include<iostream>
 8 using namespace std;
 9 
10 struct heapnode
11 {
12     int v,id;
13     bool operator < (const heapnode &b) const
14     {return v<b.v || (v==b.v && id<b.id);}
15     bool operator > (const heapnode &b) const {return b<*this;}
16 };
17 priority_queue<heapnode,vector<heapnode>,greater<heapnode> > q;
18 int n;
19 int x;
20 #define maxn 100011
21 int list[maxn],len;
22 #define LL long long
23 int find(int x)
24 {
25     if (x<=list[1]) return 0;
26     int L=1,R=len;
27     while (L<R)
28     {
29         int mid=(L+R+1)>>1;
30         if (list[mid]>=x) R=mid-1;
31         else L=mid;
32     }
33     return L;
34 }
35 struct BIT
36 {
37     int a[maxn];
38     int lowbit(int x) {return x&-x;}
39     int query(int x)
40     {
41         x++;
42         int ans=0;
43         for (;x;x-=lowbit(x)) ans+=a[x];
44         return ans;
45     }
46     void add(int x,int v)
47     {
48         x++;
49         for (;x<=n;x+=lowbit(x)) a[x]+=v;
50     }
51 }t;
52 int main()
53 {
54     scanf("%d",&n);
55     for (int i=0;i<n;i++)
56     {
57         scanf("%d",&x);
58         q.push((heapnode){x,i});
59         t.add(i,1);
60     }
61     int now=0;LL ans=1;
62     while (!q.empty())
63     {
64         int p=q.top().v;
65         list[len=1]=q.top().id;
66         q.pop();
67         while (!q.empty() && q.top().v==p)
68         {
69             list[++len]=q.top().id;
70             q.pop();
71         }
72         int tmp=find(now);
73         if (!tmp)
74         {
75             ans=ans+t.query(list[len])-t.query(now);
76             now=list[len];
77         }
78         else
79         {
80             ans=ans+t.query(list[tmp])+t.query(n-1)-t.query(now);
81             now=list[tmp];
82         }
83         for (int i=1;i<=len;i++) t.add(list[i],-1);
84     }
85     printf("%I64d
",ans);
86     return 0;
87 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/7182264.html