雜題 黑匣子(堆的簡單應用)

2021-08-14 06:08:01 字數 1904 閱讀 6549

黑匣子

時間限制:1s 記憶體限制:128mb

問題描述

black box是一種原始的資料庫。它可以儲存乙個整數陣列,還有乙個特別的變數i。最開始的時候black box是空的.而i等於0。這個black box要處理一串命令。

命令只有兩種:

add(x):把x元素放進blackbox;

get:i加1,然後輸出blackhox中第i小的數。

記住:第i小的數,就是black box裡的數的按從小到大的順序排序後的第i個元素。例如:

我們來演示一下乙個有11個命令的命令串。(如下圖所示)

現在要求找出對於給定的命令串的最好的處理方法。add和get命令分別最多200000個。現在用兩個整數陣列來表示命令串:

1.a(1),a(2),…a(m):一串將要被放進black box的元素。每個數都是絕對值不超過2000000000的整數,m$200000。例如上面的例子就是a=(3,1,一4,2,8,-1000,2)。

2.u(1),u(2),…u(n):表示第u(j)個元素被放進了black box裡後就出現乙個get命令。例如上面的例子中u=(l,2,6,6)。輸入資料不用判錯。

輸入描述

第一行,兩個整數,m,n。

第二行,m個整數,表示a(l)……a(m)。

第三行,n個整數,表示u(l)…u(n)。

輸出描述

輸出black box根據命令串所得出的輸出串,乙個數字一行。

樣例輸入

7 43 1 -4 2 8 -1000 2

1 2 6 6

樣例輸出

資料範圍

對於30%的資料,m≤10000;

對於50%的資料,m≤100000:

對於100%的資料,m≤200000。

解析

這題看似複雜,但仔細一分析,這題可以把資料分兩部分儲存:前i小的數和其餘的數,而且這兩部分都得是有序的,這便讓我們想到了優先佇列。

將前i小的數用乙個從大到小的優先佇列h2儲存,其餘數則用乙個從小到大的優先佇列h1儲存。每當新新增乙個數時,把它與h2的隊首比較,把這兩個數中小的放入h2,大的放入h1;每當要輸出乙個數時,便把h1的隊首取出並輸出(因為它肯定是第i+1小的),然後放入h2。

一道看起來很難的題目就被這樣輕鬆解決了。

**

#include#define m 200000

using namespace std;

int n,m,a[m+5],u[m+5];

priority_queue,greater> h1;//定義乙個由小到大的優先佇列h1,儲存其餘數

priority_queueh2;//定義乙個由大到小的優先佇列h2,儲存前i小的數

void read(int &x)//讀優

void write(int x)//輸優

void init()//讀入

void get()//模擬進行get操作

void work()//主要程式

//反之,不用進行操作,直接將當前的數放入h1即可

h1.push(w);//將要放入h1的數放入

while(i==u[x]&&x<=n) get(),x++;//如果在放入這個數之後要進行get操作,那麼就執行get()

}}int main()

Luogu1801 黑匣子 堆

傳送門 題意 給出兩種命令 add x 把 x 元素放進 black box get i 加 1,然後輸出 black box 中第 i 小的數。輸出每次get操作的結果。題解 注意到每次求的第k小中,k從1開始遞增。則維護乙個大根堆和乙個小根堆,大根堆裡記錄前k小的數字,小根堆裡記錄其他的數字。這...

黑匣子(優先佇列,大小根堆)

noi導刊2010提高 06 來自luogu 題目描述 black box是一種原始的資料庫。它可以儲存乙個整數陣列,還有乙個特別的變數i。最開始的時候black box是空的 而i等於0。這個black box要處理一串命令。命令只有兩種 add x 把x元素放進blackbox get i加1,...

洛谷P1801 黑匣子 堆

兩種操作 有點像對頂堆啊。每次維護乙個大根堆,保證只儲存最小的s ss個數字。其中s ss表示現在進行了s ss次get getge t操作。然後維護乙個小根堆,把其他所有數字儲存進去。這樣每次詢問完就可以把不在大根堆裡的最小的元素扔進大根堆裡。方便下一次詢問。時間複雜度o m log n o m ...