bzoj1455 羅馬遊戲

2022-06-02 06:48:07 字數 1419 閱讀 4836

time limit: 5 sec  memory limit: 64 mb

submit: 1526  solved: 639

[submit][status][discuss]

第一行乙個整數n(1<=n<=1000000)。n表示士兵數,m表示總命令數。 第二行n個整數,其中第i個數表示編號為i的士兵的分數。(分數都是[0..10000]之間的整數) 第三行乙個整數m(1<=m<=100000) 第3+i行描述第i條命令。命令為如下兩種形式: 1. m i j 2. k i

如果命令是kill,對應的請輸出被殺人的分數。(如果這個人不存在,就輸出0)

5100 90 66 99 10

7m 1 5

k 1k 1

m 2 3

m 3 4

k 5k 4

10100066

斜堆模版題 然而出題人還要加個並查集...

然而我跑得特別慢...

國際慣例是不是應該扔點東西上來啊?

——————————————————

斜堆(skew heap)也叫自適應堆(self-adjusting heap),它是左傾堆的乙個變種。和左傾堆一樣,它通常也用於實現優先佇列;作為一種自適應的左傾堆,它的合併操作的時間複雜度也是o(lg n)。

斜堆的合併操作

(01) 如果乙個空斜堆與乙個非空斜堆合併,返回非空斜堆。

(02) 如果兩個斜堆都非空,那麼比較兩個根節點,取較小堆的根節點為新的根節點。將"較小堆的根節點的右孩子"和"較大堆"進行合併。

(03) 合併後,交換新堆根節點的左孩子和右孩子。

——————————————————

1 #include2

#define rep(i,l,r) for(int i=l;i<=r;++i)

3using

namespace

std;

4const

int n=1023333;5

intn,q,v[n],l[n],r[n],x,y,f[n];

6bool

vis[n];

7char s[10];8

int find(int

x)11

int merge(int a,int

b)17

intmain()

32 }else

35 x=find(x);

36 printf("

%d\n

",v[x]);

37 vis[x]=1

;38 f[x]=merge(l[x],r[x]);

39 f[f[x]]=f[x];40}

41}42 }

view code

bzoj 1455 羅馬遊戲

link 羅馬遊戲 這道題 每次合併兩個集合 或者 每次找到某個集合中值最小的並且將其刪掉。發現直接主席樹 主席樹合併即可 但是這樣做過於不優美且 n leq 1000000 這樣做在常數上不優秀。我們考慮開堆 合併兩個堆?啟發式合併?nlog 2崩掉。那直接開斜堆 即左偏樹 或者說可並堆。這樣合併...

bzoj1455羅馬遊戲

bzoj1455羅馬遊戲 題意 維護資料結構支援合併和彈出最小值。n 1000000,m 100000 題解 可並堆,注意本題合併時要判斷兩個節點是否在同乙個堆中。本弱寫了左偏樹和斜堆,發現斜堆比左偏樹快,不知道為什麼,求神犇解答。1 include 2 include 3 include 4 de...

BZOJ1455 羅馬遊戲 左偏樹

題解 本題顯然可以用堆來實現,維護乙個大根堆 但是無法進行合併操作,於是我們想到左偏樹。定義乙個結點的斜深度為這個節點不斷向自己的右兒子走 直到為葉子節點的長度。左偏樹的 左偏 指左兒子的斜深度一定大於等於右兒子的斜深度。合併就簡單了,我們可以歸併的來維護乙個左偏樹,設需合併的兩個樹的根節點為 k1...