參考部落格:
?(巨佬i了
題目大意:給出m個城市在按直線排列,用道路連線起來,現在可以把任意的城市炸裂或者修復,問乙個城市連線了多少其他城市(包括自身)
先來講講自己初學對區間合併的理解
tree陣列記錄下區間l,r,並且記錄區間內連續字首1的數量(我記為ll),和連續字尾1的數量(我記為rr)
(sample1 :1101 那麼他的字首就是2,字尾就是1)
(sample2 :11111 字首是5,字尾是5)
給出乙個區間[1,7],它是由區間[1,4],[5,7]合成的,
那麼[1,7]區間的字首1到底有多少呢?肯定是包含了[1,4]的字首1
但是萬一[1,4]全是1呢?
那麼這時候就要加上[5,7]的字首1數量了
字尾1同理
voidpu(
int rt)
建樹是沒有什麼區別的,只是根據題意定義的,在這邊把葉子節點全部定義為1(因為長度為1的線段肯定最大也就1,並且初始所有城市都是完好的)
void
build
(int rt,
int l,
int r)
int mid=
(l+r)
>>1;
build
(lson)
;build
(rson);pu
(rt)
;}
更新也沒有什麼難度,要修改的只有一座城市,只要遞迴找到這座城市並賦值為0,然後向上更新就可以了
void
update
(int p,
int x,
int rt,
int l,
int r)
int mid=
(tree[rt]
.l+tree[rt]
.r)>>1;
if(p<=mid)
update
(p,x,rt<<
1,l,r)
;else
update
(p,x,rt<<1|
1,l,r);pu
(rt)
;}
最難的就是查詢了,理解了好久
我們一直記錄的是乙個區間的字首1和字尾1的數量,那麼我們現在題目問的是乙個城市連線其他城市的數量,這有什麼關係呢?
sample:110101
現在給出7個城市,我們要求第四個城市的連線情況,動態來看就是從這個點往左往右出發,直到碰到0停止,也就是要求乙個最長的連續1區間
我們查詢的時候一定是查到這個點被包含在連續區間內
一開始查1,7,發現4並不在他的連續區間([1,2],[7,7])內,就繼續查左子樹(因為4在左子樹上)
然後查1,4,發現4在他的連續區間內([1,2],[4,4]),那麼此時就可以直接退出了!
找到左子樹的字尾和右子樹的字首加起來就可以了
int
query
(int p,
int rt,
int l,
int r)
int mid=
(tree[rt]
.l+tree[rt]
.r)>>1;
if(p<=mid)
else
}
/**
* author1: low-equipped w_udixixi
* author2: sher丶lock
* date :2019-08-17
**/#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define pb push_back
#define rep(x,a,b) for (int x=a;x<=b;x++)
#define repp(x,a,b) for (int x=a;x#define pi 3.14159265358979323846
#define mem(a,x) memset(a,x,sizeof a)
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
using namespace std;
const
int maxn=
2e6+7;
const
int inf=
1e9;
struct node
tree[maxn]
;stack<
int> s;
voidpu(
int rt)
if(tree[rt<<1|
1].rr==tree[rt<<1|
1].r-tree[rt<<1|
1].l+1)}
void
build
(int rt,
int l,
int r)
int mid=
(l+r)
>>1;
build
(lson)
;build
(rson);pu
(rt);}
void
update
(int p,
int x,
int rt,
int l,
int r)
int mid=
(tree[rt]
.l+tree[rt]
.r)>>1;
if(p<=mid)
else
pu(rt);}
intquery
(int p,
int rt,
int l,
int r)
int mid=
(tree[rt]
.l+tree[rt]
.r)>>1;
if(p<=mid)
else
}int
main()
else
if(s[0]
=='q'
)else
if(s[0]
=='r')}
}return0;
}
感覺這只是乙個區間合併的小題,稍微寫一下增長一下理解吧,歡迎指出錯誤! 線段樹 區間合併 HDU 1540
題意 題意 d 破壞村莊,r 修復最後乙個破損的村莊,q 查詢x在內的連續區間值有多少 思路 建立線段樹,維護左右區間值。注意維護變數為 從左編開始最大連續值,從右邊開始最大值,最大連續值 為了維護最後乙個被破壞的。需要時刻記錄,並且不能只單純記錄乙個,而是需要記錄順序。滿足先入後出的棧操作,傳參即...
線段樹(區間合併)HDU 1540
題意 輸入n,m,給定n個相互連通的村莊,有m個操作,d x,表示破壞x村莊使其與相鄰的兩個村莊不相通,r 表示修復上乙個被破壞的村莊,與相鄰的兩個村莊聯通。q x表示與x相連的村莊有多少個。思路 一開始只知道是線段樹,想著肯定得用結構體記錄每個點的資訊,怎麼記錄就不知道了。然後學了線段樹區間合併。...
線段樹 區間合併
hdu 1540 tunnel wa re 詳細見 include include include include include define max 50010 define lson l,m,k 1 define rson m 1,r,k 1 1 using namespace std typ...