hdu3911 線段樹,區間合併,延遲標記

2021-07-12 04:04:32 字數 1328 閱讀 2631

題意:就是給你一段由0和1組成的序列,然後有兩種操作:0 a b就是問從a到b最長的連續的1的長度為多少,1 a b就是把從a到b的資料是一的更新為0,是零的更新為1.

思路:用乙個結構體,lone表示從最左邊數連續1的長度,lzero表示從左邊數連續0的長度,rone表示從右邊數連續1的長度,rzero表示從右邊數連續0的長度,tmax0表示連續最長的0的個數,tmax1表示連續最長的1的個數,flag用來做延遲標記.

延遲標記:當我們在對某個節點rt進行更新時,先不向其子節點更新(如果向其子節點更新,更新到葉子節點,那麼更新操作的時間複雜度就達到了o(n)),

當我們要用到該節點的後裔的時候,再將該延遲標記向下移動,這樣更新操作就仍為o(logn)的時間複雜度。

#include

using namespace std;

#define max(x,y) (x>y?x:y)

#define min(x,y) (xstruct nodestr[100005*4];

int a[100005];

void find1(int n) //像上更新

void find2(int n)//向下更新

void build(int l,int r,int n)//建樹

else

return;

}int temp=(l+r)/2;

build(l,temp,2*n);

build(temp+1,r,2*n+1);

find1(n);

}void insert(int l,int r,int n)

if(str[n].flag==1)

find2(n);

int temp=(str[n].l+str[n].r)/2;

if(r<=temp)

insert(l,r,2*n);

else

if(l>temp)

insert(l,r,2*n+1);

else

find1(n);

}int

sum(int l,int r,int n)//求1的數目

int temp=(str[n].l+str[n].r)/2;

if(str[n].flag==1)

find2(n);

if(r<=temp)

return

sum(l,r,2*n);

else

if(l>temp)

return

sum(l,r,2*n+1);

else

}int main()

else}}

}

HDU 3911 線段樹 LAZY操作 成段更新

成段更新中只有0變1,或1變0 so只用三個值記錄此段中0,1狀態即可 線段樹結構體構造 data k l1 data k l0 分別代表此區間從左端起 必須包括最左端 最長連續1和0 data k r1 data k r0 分別代表此區間從右端起 必須包括最右端 最長連續1和0 data k m1...

線段樹 區間合併 HDU 1540

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

線段樹(區間合併)HDU 1540

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