題意:輸入n,m,給定n個相互連通的村莊,有m個操作,d x,表示破壞x村莊使其與相鄰的兩個村莊不相通,r 表示修復上乙個被破壞的村莊,與相鄰的兩個村莊聯通。q x表示與x相連的村莊有多少個。
思路:一開始只知道是線段樹,想著肯定得用結構體記錄每個點的資訊,怎麼記錄就不知道了。然後學了線段樹區間合併。
首先要知道結構體記錄的資訊,當前區間 的左右邊界、 左右邊最大連續區間、總的最大連續區間 、長度。
那麼對於初始化就知道了。
然後看pushdown函式,直到左右兒子資訊要更新父節點的資訊(詳細看注釋)
線段樹的更新就是單點修改,當找到要更新的節點時,就要更新這個節點的資訊了。同時利用回溯pushdown。
單點查詢:如果能找到那個點,就返回最大連續區間長度,對於查詢寫了個式子,模模糊糊有點理解:(也就是說,如果處在左兒子的右邊最大區間,該 右邊最大區間 和 右兒子最大連續左區間一定相連 (這是性質),加上即可
#include#include#includeusing namespace std;
struct node
ans[200010];/*記錄 左端最大連續區間 右端最大連續區間 最大連續區間*/
void pushdown(int o)
void build(int l,int r,int o)/*初始化*/
void update(int o,int x,int judge)/*單點修改*/
int mid=(ans[o].l+ans[o].r)>>1;
if(x<=mid) update(o<<1,x,judge);
else update(o<<1|1,x,judge);
pushdown(o);
}int query(int o,int x)
int mid=(ans[o].l+ans[o].r)>>1;
// printf("%d %d\n",x,mid);/*相鄰節點之間區間是連續的*/
if(x<=mid)
else
}int main()
else if(a[0]=='q')
else if(a[0]=='r')}}
return 0;
}
線段樹 區間合併 HDU 1540
題意 題意 d 破壞村莊,r 修復最後乙個破損的村莊,q 查詢x在內的連續區間值有多少 思路 建立線段樹,維護左右區間值。注意維護變數為 從左編開始最大連續值,從右邊開始最大值,最大連續值 為了維護最後乙個被破壞的。需要時刻記錄,並且不能只單純記錄乙個,而是需要記錄順序。滿足先入後出的棧操作,傳參即...
HDU 1540 線段樹左右區間合併
題目大概的意思就是求當前這個村莊,左右連續的村莊共有幾個,包括自己。思路 比較容易想到的就是把用線段樹劃分的每乙個區間的左右連續區間長度記錄下來,然後嘗試著吧x這個村莊的左右連續並且沒被摧毀的村莊個數連起來,就能得出答案了。具體看 的注釋 include include include includ...
線段樹基礎之區間合併HDU1540
參考部落格 巨佬i了 題目大意 給出m個城市在按直線排列,用道路連線起來,現在可以把任意的城市炸裂或者修復,問乙個城市連線了多少其他城市 包括自身 先來講講自己初學對區間合併的理解 tree陣列記錄下區間l,r,並且記錄區間內連續字首1的數量 我記為ll 和連續字尾1的數量 我記為rr sample...