hdu 1540線段樹刷題

2022-07-23 18:27:20 字數 2814 閱讀 5364

title: hdu-1540線段樹刷題

date: 2018-10-18 19:55:21

tags:

哇,,,這道線段樹的題可以說是到目前為止我所做過的最難的一道了吧qaq,,,,,,

一開始讀完題就是一臉懵逼,,,,完全不知道該從**下手,,,就是知道這是一道線段樹的題也不知道該怎麼下手啊啊啊,,,,

最後還是看了kaungbin大佬的**,,,qaq

光是讀**就花了一兩個小時,,,(不過也有可能和今天賊困有關,,,腦袋不怎麼轉啊

大概的題意就是一串在一條線上的村莊,,或者說是點,,,一開始都為1,,,然後有三種不同的操作,,,

一開始我看到有需要上一次操作的情況,,就想著要將這些d操作儲存下來,,適合這道題的就是棧,,,

然後就是詢問了,,,我那時想著既然要求a周圍這些1的個數,,那我就找到兩端的0不就行了,,,然後從這裡就徹底的腦抽了,,,又想著用線段樹去求這段區間的和,,,,然後結果顯而易見,,,,t了,,,

因為,,這種想法線段樹根本沒有用啊!!!!都找出那兩端的0所在的位置直接減不就行了,,,這不就是裸暴力嗎,,,,,哇,,,被自己蠢哭(๐॔˃̶ᗜ˂̶๐॓),,,,

首先將這段線劃分成多個區段,,,每個區段儲存的資訊有:從這去區段的左端點開始最長的連續1的個數ll從這個區段右端點開始的最長的連續1的個數rl、 還有這個區段最大的連續點的個數ml。。。

建樹:ll = rl = ml = 區間長

更新

葉子節點置一置零,,,

左右遞迴更新

其他區間:(pushup())

父節點.ll = 左節點.ll 父節點.rl = 右節點.rl

父節點.ml取左右節點的最大的乙個ml

若左節點的rl + 右節點的ll > 父節點的ml,,,,就更新為前者

對於父節點的ll,rl

如果左節點的ll為左節點的長度,,,就說明左節點從左端點開始的連續1的最大的個數就為左節點包含的點的個數,,,所以此時的父節點的ll就要和右節點的ll合併

同理,,,父節點的rl也要進行這樣的判斷

查詢

對於一些特殊的區間直接返回該區間的最大的連續1的個數也就是ml

當loc在中點左時,,,就要從左節點來判斷,,,判斷的條件是loc是否超出了rl的最左端(畫圖更容易理解一些),,,超出的話就說明loc所在的連續的1一部分是在左節點的rl裡另一部分是在右節點的ll裡,,,就分成兩個點查詢,,,乙個是在左節點的loc,,,另乙個時在右節點的mid+1那個點

同理,,若在中點的右時也有類似的判斷,,,

大體上說就是不斷地判斷要找到那個點相對ll,rl的位置,,,最後把遞迴查詢到的結果合併就行了,,,

字醜見諒,,,,(不過應該沒人看把,,,,

//遞迴更新

//先更新父節點的兩個,ll,rl

node[rt].ll = node[rt << 1].ll;

node[rt].rl = node[rt << 1 | 1].rl;

//然後是父節點的ml

node[rt].ml = max(node[rt << 1].ml , node[rt << 1 | 1].ml);

node[rt].ml = max(node[rt].ml , node[rt << 1].rl + node[rt << 1 | 1].ll);

//父節點的ll,rl可能就是左右節點的ll,,rl,,,,當剛好是子節點的全部時還要加上另乙個區間的一部分

if(node[rt << 1].ll == node[rt << 1].r - node[rt << 1].l + 1)

node[rt].ll += node[rt << 1 | 1].ll;

if(node[rt << 1 | 1].rl == node[rt << 1 | 1].r - node[rt << 1 | 1].l + 1)

node[rt].rl += node[rt << 1].rl;

return;

}int query(int rt , int loc)

else

}int main()

else if(c == 'q')

else}}

}return 0;

}//kaungbin

線段樹 區間合併 HDU 1540

題意 題意 d 破壞村莊,r 修復最後乙個破損的村莊,q 查詢x在內的連續區間值有多少 思路 建立線段樹,維護左右區間值。注意維護變數為 從左編開始最大連續值,從右邊開始最大值,最大連續值 為了維護最後乙個被破壞的。需要時刻記錄,並且不能只單純記錄乙個,而是需要記錄順序。滿足先入後出的棧操作,傳參即...

HDU 1540 線段樹(區間查詢)

有n個點,每兩個點之間存在一條通路,d x代表摧毀x點,r代表修復最近摧毀的乙個點。q x代表查詢x點能連線多少個村莊 包括自己 比較複雜的線段樹。狀態需要用結構體儲存。l,r代表左邊界和右邊界,ls代表左連續區間長度,rs代表右連續區間長度。ms代表區間內最大連續長度。初始化過程都初始化成1就可以...

線段樹(區間合併)HDU 1540

題意 輸入n,m,給定n個相互連通的村莊,有m個操作,d x,表示破壞x村莊使其與相鄰的兩個村莊不相通,r 表示修復上乙個被破壞的村莊,與相鄰的兩個村莊聯通。q x表示與x相連的村莊有多少個。思路 一開始只知道是線段樹,想著肯定得用結構體記錄每個點的資訊,怎麼記錄就不知道了。然後學了線段樹區間合併。...