HDU 1540 線段樹左右區間合併

2021-09-09 01:13:23 字數 1562 閱讀 6425

題目大概的意思就是求當前這個村莊,左右連續的村莊共有幾個,包括自己。

思路:比較容易想到的就是把用線段樹劃分的每乙個區間的左右連續區間長度記錄下來,然後嘗試著吧x這個村莊的左右連續並且沒被摧毀的村莊個數連起來,就能得出答案了。

具體看**的注釋

#include #include #include #include #include #include using namespace std;

typedef long long ll;

const int maxn = 5e4+10;

const int inf = 0x3f3f3f3f;

int a[maxn], left[4*maxn], right[4*maxn], zero[4*maxn], x; // zero用來記錄當前區間有幾個被摧毀的村莊

bool l, r, op; // l, r分別表示左右界有沒有找到,op == 1 表示摧毀

void init(int cur, int l, int r)

int mid = (r+l)/2;

init(cur*2, l, mid); init(cur*2+1, mid+1, r);

left[cur] = left[cur*2]; right[cur] = right[cur*2+1]; // 如果左子樹全都是1,那麼當前區間的左連續長度還需要

if (!zero[cur*2]) left[cur] += left[cur*2+1]; // 加上右子樹的左連續區間,以此類推

if (!zero[cur*2+1]) right[cur] += right[cur*2]; // 通過zero能判斷當前區間是否全都是1

}void updata(int cur, int l, int r) else if (!op && !a[l])

}return;

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

if (x <= mid) updata(cur*2, l, mid); // 如果修改的是左子樹,右子樹可以不用遞迴,但是右子樹的左連續區間可能會

else updata(cur*2+1, mid+1, r); // 因為左子樹的修改而發生變化,所以右子樹的區間記錄也要更新

left[cur] = left[cur*2]; right[cur] = right[cur*2+1];

if (!zero[cur*2]) left[cur] += left[cur*2+1];

if (!zero[cur*2+1]) right[cur] += right[cur*2];

zero[cur] = zero[cur*2]+ zero[cur*2+1];

}int solve(int cur, int l, int r)

int m1, m2, mid = (r+l)/2;

if (x <= mid)

} else

}}int main (void)

else if (ch == 'd') else }}

return 0;

}

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