如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作:
操作1: 1 x y 將第x個數和第y個數所在的小根堆合併(若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作)
操作2: 2 x 輸出第x個數所在的堆最小數,並將其刪除(若第x個數已經被刪除,則輸出-1並無視刪除操作)
輸入格式:
第一行包含兩個正整數n、m,分別表示一開始小根堆的個數和接下來操作的個數。
第二行包含n個正整數,其中第i個正整數表示第i個小根堆初始時包含且僅包含的數。
接下來m行每行2個或3個正整數,表示一條操作,格式如下:
操作1 : 1 x y
操作2 : 2 x
輸出格式:
輸出包含若干行整數,分別依次對應每乙個操作2所得的結果。
輸入樣例#1: 複製
5 51 5 4 2 3
1 1 5
1 2 5
2 21 4 2
2 2
輸出樣例#1: 複製
12
當堆裡有多個最小值時,優先刪除原序列的靠前的,否則會影響後續操作1導致wa。
時空限制:1000ms,128m
資料規模:
對於30%的資料:n<=10,m<=10
對於70%的資料:n<=1000,m<=1000
對於100%的資料:n<=100000,m<=100000
樣例說明:
初始狀態下,五個小根堆分別為:、、、、。
第一次操作,將第1個數所在的小根堆與第5個數所在的小根堆合併,故變為四個小根堆:、、、。
第二次操作,將第2個數所在的小根堆與第5個數所在的小根堆合併,故變為三個小根堆:、、。
第三次操作,將第2個數所在的小根堆的最小值輸出並刪除,故輸出1,第乙個數被刪除,三個小根堆為:、、。
第四次操作,將第4個數所在的小根堆與第2個數所在的小根堆合併,故變為兩個小根堆:、。
第五次操作,將第2個數所在的小根堆的最小值輸出並刪除,故輸出2,第四個數被刪除,兩個小根堆為:、。
故輸出依次為1、2。
#include#include#include
#include
#include
using
namespace
std;
const
int n=1e5+5
;inline
intread()
bool
del[n];
intn,m;
struct
node
}a[n];
struct
node
node[n];
intfa[n];
int find(int
x)int merge(int x,int
y)int erase(int
x)int
opt,x,y,new_r;
intmain()
while(m--)
else
x=find(x);
printf(
"%d\n
",a[x].v);
new_r=erase(x);
fa[x]=fa[new_r]=new_r;
del[x]=true
; }
}return0;
}
P3377 模板 左偏樹 可並堆
開始時n nn個只有乙個數的集合,要求支援 合併兩個集合 查詢乙個集合中的最小值並刪除 左偏樹就是維護乙個滿足以下性質的樹 對於v al xval x valx 有val x llsx val xva lx llsx 且v al x lrsx val xva lx lrsx 對於任何節點有左子樹的深...
P3377 模板 左偏樹(可並堆)
如題,一開始有n個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 操作1 1 x y 將第x個數和第y個數所在的小根堆合併 若第x或第y個數已經被刪除或第x和第y個數在用乙個堆內,則無視此操作 操作2 2 x 輸出第x個數所在的堆最小數,並將其刪除 若第x個數已經被刪除,則輸出 1並無視刪...
P3377 模板 左偏樹(可並堆)
如題,一開始有 nn 個小根堆,每個堆包含且僅包含乙個數。接下來需要支援兩種操作 1 x y 將第 xx 個數和第 yy 個數所在的小根堆合併 若第 xx 或第 yy 個數已經被刪除或第 xx 和第 yy 個數在用乙個堆內,則無視此操作 2 x 輸出第 xx 個數所在的堆最小數,並將這個最小數刪除 ...