一副撲克牌有n
'>
n張牌。一般你買的一副新撲克牌裡除了這n
'>
n張牌外還會有一些張特殊的牌,如果你不小心弄丟了n
'>
n張牌中的某一張,就可以用特殊牌來代替,但是如果你弄丟兩張的話就沒有辦法了,因為特殊牌上的圖案是一樣的。
現在你得到了很多撲克牌,準確來說,n
'>n
n種牌你各有a1,
a2,…
,an'>a1,a2,…,an
'>
n種普通牌各一張組成,也可以由n−1
'>n−1
種普通牌各一張再加一張特殊牌組成。
請你設計出一種方案,整理出盡可能多的牌。
第一行給出n
'>n
和b'>b
。第二行給出a1,
a2,…
,an'>a1,a2,…,an
。輸出最多能整理出的牌的副數。
5 55 5 5 5 5
6
【資料規模及約定】
對於20%的資料,1≤n
≤100
'>1≤n≤100
,牌的數量小於100
'>100
。對於40%的資料,1≤n
≤3000
'>1≤n≤3000
。對於100%的資料,1≤n
≤1000000
'>1≤n≤1000000
,牌的數量≤10^610
6'>。1≤
n≤1000000
'>10
6'>思路:1≤
n≤1000000
'>10
6'>本題的思路思路為貪心+堆,首先可以確定一開始的全由n種牌組成的數目為min(a[i]),因此我們每次對全由n種牌組成的採取去掉一張換為特殊拍的策略,同時我們需要保證此刻整副撲克牌中的最小值最大,也就是我們再換牌時,需要先取出小根堆首的牌,然後將其牌數加一,並用comp此變數來表示此刻全由n種撲克牌組成的數目,由於我們每次採取這樣的換牌策略,因此每個時刻comp都應該發生變化,而小根堆中的最小的元素代表的則是全由n種牌組成的個數以及由n-1種牌加一種特殊牌組成的個數的總數,這就是我們應使最小值最大的原因。而每次換牌的時候我們將其從1到comp進行迴圈,因為此刻剩餘的全由n種牌組成的個數為comp。而迴圈結束的條件為進行一次操作後小根堆中最小的元素的大小沒有發生變化或者是剩餘的特殊牌等於零了。1≤
n≤1000000
'>10
6'>**:
1 #include2 #include3 #include4 #include5 #include6 #include7using
namespace
std;
8#define maxn 1000010
9#define clear(a) memset(a,0,sizeof a)
1011
intn,b,ans,comp;
12int
a[maxn];
13 priority_queueq;
1415
intmain()
1623 ans=comp=-q.top();
24while(1)25
35 temp=-q.top();
36if(ans-temp==0)break
;37 comp=temp-ans;
38 ans=temp;39}
40 cout<"\n"
;41return0;
42 }
一本通 高手訓練 遊戲通關
遊戲通關 xy在玩乙個包含n n 個任務的遊戲。每個任務完成時限為t i ti 你可以認為還沒開始做任務時的時間為0 0 獎勵為w i wi 由於xy技術的嫻熟以及任務的簡單,對於每個任務,他都可以在乙個單位時間內完成。xy想要知道他能夠獲得的最多的獎勵。第一行乙個整數n n,表示需要完成的任務數目...
一本通 高手訓練 1781 死亡之樹 狀態壓縮dp
link 死亡之樹 關於去重 還是有講究的。題目求本質不同的 具有k個葉子節點的樹的個數 不能上矩陣樹。點數很少容易想到裝壓dp 考慮如何刻畫樹的形狀 發現乙個維度做不了 所以。設狀態 f i j 表示 點的集合為i葉子集合的點為j的方案樹。這樣我們就能知道這棵樹大致的樣子 空間 為 2 當然 如果...
佇列(一本通)
這道題重點是關係的轉換和初始化 include include include includeusing namespace std int a 101 記錄接著的的那個節點 int n,m int main int ans void bfs int x,int y int main cout in...