題意:就是給你一段由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相連的村莊有多少個。思路 一開始只知道是線段樹,想著肯定得用結構體記錄每個點的資訊,怎麼記錄就不知道了。然後學了線段樹區間合併。...