POJ 2808 校門外的樹(線段樹入門)


題目描述
某校大門外長度為L的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1米。我們可以把馬路看成一個數軸,馬路的一端在數軸0的位置,另一端在L的位置;數軸上的每個整數點,即0,1,2,……,L,都種有一棵樹。
馬路上有一些區域要用來建地鐵,這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的起始點和終止點的坐標都是整數,區域之間可能有重合的部分。現在要把這些區域中的樹(包括區域端點處的兩棵樹)移走。
你的任務是計算將這些樹都移走后,馬路上還有多少棵樹。
輸入
輸入的第一行有兩個整數L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表馬路的長度,M代表區域的數目,L和M之間用一個空格隔開。接下來的M行每行包含兩個不同的整數,用一個空格隔開,表示一個區域的起始點 和終止點的坐標。
輸出
輸出包括一行,這一行只包含一個整數,表示馬路上剩余的樹的數目。
樣例輸入
500 3150 300100 200470 471
樣例輸出
298
線段的區間覆蓋,我把這道題當作自己線段樹的入門題。線段樹的核心思想是以空間換時間。以4倍的空間復雜度來將O(n)的算法優化成O(logn)。
如果現在的節點在樹的數組中的下標為now, 則它的左兒子的下標就是now*2,右兒子的下標就是now*2+1。
如果現在節點所代表的區間范圍是[l,r],則它的左兒子代表的區間范圍是[l,mid],右兒子是[mid+1,r](mid=(l+r)/2);
建樹的時候按照先序遍歷的順序來建樹。
代碼如下:
 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 #define MAXN 40040
 5 #define inf 0x3f3f3f3f
 6 struct segTree
 7 {
 8     int l,r,sum;
 9 }tree[MAXN];
10 void buildTree (int now,int ll,int rr)
11 {
12     tree[now].l=ll;
13     tree[now].r=rr;
14     if (ll==rr)//如果當前區間長度為1
15     {
16         tree[now].sum=1;//這個區間最開始只有1棵樹
17         return;//不寫return會炸...
18     }
19     int mid=(ll+rr)/2;
20     int lch=now*2,rch=now*2+1;
21     buildTree(lch,ll,mid);//建左子樹
22     buildTree(rch,mid+1,rr);//建右子樹
23 tree[now].sum=tree[lch].sum+tree[rch].sum;
24 //父親節點樹木是左右子節點的樹木個數的和
25 }
26 void update (int now,int ll,int rr,int x,int y)
27 {
28 if (ll>y||rr<x||tree[now].sum==0) 
29 //當[x,y]與當前區間[ll,rr]沒有交集時,或此區間的樹都已經被拔光了
30 return ;
31     if (x<=ll&&y>=rr) 
32     {
33         tree[now].sum=0;//將此區間樹拔光
34         return ;
35     }
36     int mid=(ll+rr)/2;
37     int lch=now*2,rch=now*2+1;
38     update(lch,ll,mid,x,y);//二分尋找[ll,rr],使其與[x,y]有交集
39     update(rch,mid+1,rr,x,y);
40     tree[now].sum=tree[lch].sum+tree[rch].sum;
41 }
42 int L,M;
43 int main()
44 {
45     //freopen("de.txt","r",stdin);
46     scanf("%d%d",&L,&M);
47     buildTree(1,1,1+L);
48     for (int i=0;i<M;++i)
49     {
50         int left,right;
51         scanf("%d%d",&left,&right);
52         update(1,1,1+L,left+1,right+1);
53     }
54     printf("%d\n",tree[1].sum);
55     return 0;
56 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM