黑匣子
時間限制: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 ...