線段樹的數據結構:
- const int SIZE = 10010;
- const double EPS = 1e-6;
- int MAX = 99999999;
- struct node // the node of line tree
- {
- int i,j; // 區間範圍
- node * lson;
- node * rson;
- int count; // 線段覆蓋條數
- int m; // 測度
- int line; // 連續段數
- int lbd,rbd; // 用來計算連續段數
- node(int l,int r)
- {
- i = l,j = r;
- count = m = line = lbd = rbd = 0;
- lson = rson = NULL;
- }
- };
m:測度,通俗點說,就是該區間中被覆蓋過線段的總長度。當該區間的count>1時,m等於該區間的長度,如果是離散化之後的線段樹,就加上對應的線段的長度。如果這個節點不是內部節點而是葉節點並且count=0,那m就等於0。如果這個節點的count等於0,但是他是內部節點,那麼m就等於他左右子節點的m值的和。
line連續段數:就是該區間上連續線段的條數,比如線段樹[1,10]上,有兩條線段[1,5],[8,10],那麼[1,10]這個區間上的連續線段的條數就是2;如果有兩條線段是[1,5],[5,10],那麼該區間上連續線段條數就是1。由此可以看出,連續線段條數,與該節點的左右子節點上的左右端點的覆蓋情況有關,因此還有設立2個域lbd,rbd表示該區間的左右端點的覆蓋情況。假如count>0,說明這個區間被一條線段覆蓋了,那麼顯然這個區間的line等於1;假如這個節點是葉節點並且count=0,那麼line顯然等於0;假如這個區間的count=0但是他是內部節點,就又要分2種情況:①左子節點的rbd和右子節點lbd都等於1,即上例中[1,5],[5,10]的情況,那麼line就等於1。 ②左子節點的rbd和右子節點lbd至少有1個不等於1,即上例中[1,5],[8,10]的情況,那麼line就等於2。對於lbd,rbd的定義,可以這樣該區間的lbd等於他的左子節點的lbd,rbd等於他的右子節點的rbd。
---------------------------------------------線段樹的完整代碼--------------------------------------------------
- struct node // the node of line tree
- {
- int i,j; // 區間範圍
- node * lson;
- node * rson;
- int count; // 線段覆蓋條數
- int m; // 測度
- int line; // 連續段數
- int lbd,rbd; // 用來計算連續段數
- node(int l,int r)
- {
- i = l,j = r;
- count = m = line = lbd = rbd = 0;
- lson = rson = NULL;
- }
- };
- class LineTree
- {
- node * head;
- /* 以下函數內部使用,可不用考慮 */
- void init(node * pnode = NULL)
- {
- head = pnode;
- }
- void updateM()
- {
- if (head->count > 0) // 被覆蓋滿
- head->m = head->j - head->i;
- else if (head->j - head->i == 1) // 該節點爲葉節點
- head->m = 0;
- else // 其他內部節點的情況
- head->m = (head->lson)->m + (head->rson)->m;
- }
- void updateLine()
- {
- if (head->count > 0)
- head->lbd = head->rbd = head->line = 1;
- else if (head->j - head->i == 1)
- head->lbd = head->rbd = head->line = 0;
- else
- {
- head->lbd = (head->lson)->lbd;
- head->rbd = (head->rson)->rbd;
- head->line = (head->lson)->line + (head->rson)->line - (head->lson)->rbd * (head->rson)->lbd;
- }
- }
- public:
- LineTree()
- {
- head = NULL;
- }
- void clear() // 清空線段數
- {
- if(head == NULL)
- return;
- LineTree temp;
- temp.init(head->lson);
- temp.clear();
- temp.init(head->rson);
- temp.clear();
- delete head;
- head = NULL;
- }
- void build(int l,int r) // 建立線段樹,區間[l,r]
- {
- head = new node(l,r);
- if (r - l > 1)
- {
- int k = (l + r) / 2;
- LineTree temp;
- temp.build(l,k);
- head->lson = temp.head;
- temp.init();
- temp.build(k,r);
- head->rson = temp.head;
- }
- }
- void insert(int l,int r) // 插入一條線段
- {
- if (l <= head->i && r >= head->j)
- (head->count)++;
- else
- {
- LineTree temp;
- if (l < (head->i+head->j)/2)
- {
- temp.init(head->lson);
- temp.insert(l,r);
- }
- if (r > (head->i+head->j)/2)
- {
- temp.init(head->rson);
- temp.insert(l,r);
- }
- }
- updateM();
- updateLine();
- }
- void del(int l,int r) // 刪除一條線段
- {
- if (l <= head->i && head->j <= r)
- (head->count)--;
- else
- {
- LineTree temp;
- if (l < (head->i+head->j)/2)
- {
- temp.init(head->lson);
- temp.del(l,r);
- }
- if (r > (head->i+head->j)/2)
- {
- temp.init(head->rson);
- temp.del(l,r);
- }
- }
- updateM();
- updateLine();
- }
- int GetM() // 測度
- {
- return head->m;
- }
- int GetLine() // 連續段數
- {
- return head->line;
- }
- int GetCov() // 覆蓋線段數
- {
- return head->count;
- }
- ~LineTree() {}
- };