日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

实用算法实现-第6篇线段树

發布時間:2024/4/11 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 实用算法实现-第6篇线段树 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

6.1??? 線段樹簡介

線段樹的定義如下:

?? ? ? ?一棵二叉樹,記為T (a,b),參數a,b表示該結點表示區間[a,b]。區間的長度b-a記為L。遞歸定義T[a,b]:

?? ? ? ?若L>1 :[a, (a+b) div 2]為 T的左兒子

?? ? ? ? ? ? ? ? ? ? ? ?[(a+b)div 2,b]為T的右兒子。
?? ? ? ?若L=1 :T為一個葉子結點。


表示區間[1, 10]的線段樹表示如下:



樹一般有兩種形式:1、以點為結點。2、以線段為結點。區別如圖:上面一個以線段為結點,下面一個以點為結點:





對線段樹存在:

定理:線段樹把區間上的任意一條線段都分成不超過2logL條線段。

這個結論為線段樹能在O(logL)的時間內完成一條線段的插入、刪除、查找等工作,提供了理論依據。


對線段樹的可以進行擴展。

1.? 測度。結點所表示區間中線段覆蓋過的長度,存儲在各結點中。

2.? 獨立線段數。區間中互不相交的線段條數。

3.? 權和。區間所有元線段的權和。


測度的遞推公式如下:

?? ? ? ? ? ? ? ??a[j] - a[i] ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?該結點 Count>0

M = ? ? ? ? ?0 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?該結點為葉結點且 Count=0

?? ? ? ? ? ? ? ??Leftchild ↑ .M + Rightchild ↑ .M ? ? ? ? 該結點為內部結點且 Count=0連續段數

這里的連續段數指的是區間的并可以分解為多少個獨立的區間。如 [1 , 2] ∪[2,3]∪ [5 , 6] 可以分解為兩個區間[1 , 3] 與 [5 , 6] ,則連續段數為 2 。增加一個數據域 Lines_Tree.line 表示該結點的連續段數。 Line 的討論比較復雜,內部結點不能簡單地將左右孩子的 Line 相加。所以再增加 Lines_Tree.lbd 與 Lines_Tree.rbd 域。定義如下: ?

?? ? ? ? ? ? ? ? 1???左端點 I 被描述區間蓋到

lbd? =?

?? ? ? ? ? ? ? ? 0??? 左端點 I 不被描述區間蓋到

?

?? ? ? ? ? ? ? ?1???? 右端點 J 被描述區間蓋到

rbd? =?

?? ? ? ? ? ? ? ?0???? 右端點 J 不被描述區間蓋到

?

lbd 與 rbd 的實現:

?? ? ? ? ? ? ? ?1? 該結點 count > 0

lbd? = ? ? ?0? 該結點是葉結點且 count = 0

?? ? ? ? ? ? ? ?leftchild ↑ .lbd??? 該結點是內部結點且 Count=0

?? ? ? ? ? ? ? ?1? 該結點 count > 0

rbd? =??? 0? 該結點是葉結點且 count = 0

?? ? ? ? ? ? ? ?rightchild ↑ .rbd?? 該結點是內部結點且 Count=0

有了 lbd 與 rbd , Line 域就可以定義了:

?? ? ? ? ? ? ? ?1? 該結點 count > 0

Line = ? ? 0? 該結點是葉結點且 count =0

?? ? ? ? ? ? ? ?Leftchild ↑ .Line? +? Rightchild ↑.Line? -? 1 ?當該結點是內部結點且 Count=0 , Leftchild ↑ .rbd = 1 且 Rightchild ↑ .lbd = 1

?? ? ? ? ? ? ? ?Leftchild ↑.Line? +? Rightchild ↑ .Line?? 當該結點是內部結點且 Count=0 , Leftchild ↑ .rbd 與 Rightchild ↑ .lbd 不都為1

6.2??? 利用線段樹實現區間的動態插入和刪除

6.2.1???實例

PKU JudgeOnline, 1151, Atlantis.

6.2.2???問題描述

在二維平面分部著一些矩形,矩形有可能重合。求矩形的總面積。

6.2.3???分析

這個題在《算法藝術與信息學競賽》中第一章介紹數據結構時,講到線段樹的時候有解題分析。

用線段樹來記載縱向上是不是被覆蓋,用測度來表示區間中被覆蓋了多少長度。

為了降低復雜度,可以將坐標離散化,如下圖所示:

從左到右掃描長方形的左側邊和右側邊,如果是左側邊則加入線段樹中,否則從線段書中刪除。同時用橫向掃描的距離乘以線段樹的測度,就得到了掃描過了的被覆蓋的面積。

本題和PKU JudgeOnline,1117, Picture題都對線段樹進行了擴展。本題只用到了測度的擴展,而1117題還用到了獨立線段數的擴展。

6.2.4???程序

//離散化+ 線段樹+ 掃描線 //本題與JudgeOnline 1177 picture 極相似,現在回想起來甚至比1177 還要簡單一些.與1177 不同的是本題中的坐標是浮點 //類型的故不能將坐標直接離散.我們必須為它們建立一個對應關系,用一個整數去對應一個浮點數 //這樣的對應關系在本題的數組y[] 中 #include<iostream> #include<algorithm> #include<cmath> #include<iomanip> using namespace std; struct node{ int st, ed,c; //c : 區間被覆蓋的層數,m: 區間的測度 double m; }ST[802]; struct line{ doublex,y1,y2; //縱方向直線, x:直線橫坐標, y1 y2:直線上的下面與上面的兩個縱坐標 bools; //s = 1: 直線為矩形的左邊, s = 0:直線為矩形的右邊 }Line[205]; double y[205],ty[205]; //y[] 整數與浮點數的對應數組;ty[]:用來求y[]的輔助數組 void build(int root, int st, int ed){ ST[root].st = st; ST[root].ed = ed; ST[root].c = 0; ST[root].m = 0; if(ed - st> 1){ int mid= (st+ed)/2; build(root*2, st, mid); build(root*2+1, mid, ed); } } inline void updata(int root){ if(ST[root].c> 0) //將線段樹上區間的端點分別映射到y[]數組所對應的浮點數上,由此計算出測度 ST[root].m = y[ST[root].ed-1] -y[ST[root].st-1]; else if(ST[root].ed - ST[root].st == 1) ST[root].m = 0; elseST[root].m = ST[root*2].m + ST[root*2+1].m; } void insert(int root, int st, int ed){ if(st <=ST[root].st && ST[root].ed <= ed){ ST[root].c++; updata(root); return; } if(ST[root].ed- ST[root].st == 1)return ;//不出錯的話這句話就是冗余的 int mid =(ST[root].ed + ST[root].st)/2; if(st <mid) insert(root*2, st, ed); if(ed >mid) insert(root*2+1, st, ed); updata(root); } void Delete(int root, int st, int ed){ if(st <=ST[root].st && ST[root].ed <= ed){ ST[root].c--; updata(root); return; } if(ST[root].ed- ST[root].st == 1)return ; //不出錯的話這句話就是冗余的 int mid =(ST[root].st + ST[root].ed)/2; if(st <mid) Delete(root*2, st, ed); if(ed >mid) Delete(root*2+1, st, ed); updata(root); } int Correspond(int n, double t){ //二分查找出浮點數t 在數組y[]中的位置(此即所謂的映射關系) intlow,high,mid; low = 0; high = n-1; while(low< high){ mid = (low+high)/2; if(t> y[mid]) low = mid + 1; elsehigh = mid; } returnhigh+1; } bool cmp(line l1, line l2){ return l1.x< l2.x; } int main() { intn,i,num,l,r,c=0; doublearea,x1,x2,y1,y2; while(cin>>n,n){ for(i =0; i < n; i++){ cin>>x1>>y1>>x2>>y2; Line[2*i].x = x1; Line[2*i].y1 =y1; Line[2*i].y2 = y2; Line[2*i].s = 1; Line[2*i+1].x = x2; Line[2*i+1].y1= y1; Line[2*i+1].y2 = y2; Line[2*i+1].s = 0; ty[2*i] = y1; ty[2*i+1] = y2; } n <<= 1; sort(Line, Line+n, cmp); sort(ty, ty+n); y[0] = ty[0]; //處理數組ty[]使之不含重覆元素,得到新的數組存放到數組y[]中 for(i=num=1;i < n; i++) if(ty[i]!= ty[i-1]) y[num++] = ty[i]; build(1, 1, num); //樹的葉子結點與數組y[]中的元素個數相同,以便建立一一對應的關系 area = 0; for(i =0; i < n-1; i++){ //由對應關系計算出線段兩端在樹中的位置 l = Correspond(num, Line[i].y1); r = Correspond(num, Line[i].y2); if(Line[i].s)//插入矩形的左邊 insert(1, l, r); else //刪除矩形的右邊 Delete(1, l, r); area += ST[1].m * (Line[i+1].x -Line[i].x); } cout<<"Testcase #"<<++c<<endl<<"Totalexplored area: "; cout<<fixed<<setprecision(2)<<area<<endl<<endl; } return 0; }

6.3??? 計算數組區間第K大的數

PKU JudgeOnline, 2761, Feed the dogs則是線段樹的另外一個應用:實用線段樹來計算數組區間[i, j]中元素第k小(或第K大)的數。只要添寫一個函數,根據線段樹中每個結點的覆蓋樹木來判斷第k大的樹是哪一個。

當初始化,或者區間[i, j]發生變化時,需要對線段樹進行添加或者刪除操作。每當增加(或刪除)一個大小為X的點時,就在樹上添加(或刪除)一條(X,MaxLen)的線段(不含端點),當要查詢一個點的排名時,只要看看其上有多少條線段就可以了。

int query(int root, intcount) { if(count<= ST[root].c){ returnST[root].st; }else if(ST[root].ed - ST[root].st == 1){ returnST[root].ed; } count -= ST[root].c; if(count<= ST[root*2+1].c){ returnquery(root*2, count); }else{ returnquery(root*2+1, count); } }
1.4??? 實例

PKU JudgeOnline, 1151, Atlantis.

PKU JudgeOnline, 1117, Picture.

PKU JudgeOnline, 2761, Feed the dogs.

PKU JudgeOnline, 2528, Mayor'sposters.

本文章歡迎轉載,請保留原始博客鏈接http://blog.csdn.net/fsdev/article

轉載于:https://www.cnblogs.com/jpa2/archive/2011/10/13/2527921.html

總結

以上是生活随笔為你收集整理的实用算法实现-第6篇线段树的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产三级av在线播放 | 国产无套精品一区二区三区 | 偷拍亚洲视频 | 纯爱无遮挡h肉动漫在线播放 | 91天天爽 | 一级一毛片| 午夜影院免费看 | 黄色大片一级片 | 久久嫩草视频 | 久久精品一区二区免费播放 | 午夜小影院 | 久草中文在线视频 | 网站免费黄色 | 国产露脸无套对白在线播放 | 火影黄动漫免费网站 | 波多野结衣电车 | 无码aⅴ精品一区二区三区 精品久久在线 | 精品久久久久久久无码 | 91网国产| 欧美日韩精品一区二区三区四区 | 天堂…中文在线最新版在线 | 免费人妻精品一区二区三区 | 亚洲成人影音 | 超碰在线日韩 | 日日干夜夜爽 | 国产福利片在线 | 午夜影院在线观看 | 国产欧美久久久久久 | 国产巨乳在线观看 | 国产精品99精品无码视 | 久热精品在线视频 | 亚洲区小说区图片区qvod | 狠狠躁天天躁夜夜躁婷婷 | 日韩人妻无码精品久久久不卡 | 爱如潮水3免费观看日本高清 | 久久久久爱 | 超碰人人人 | 国产成人久久 | 8x8ⅹ8成人免费视频观看 | 久久黄色片视频 | 天天操夜夜操狠狠操 | 一区二区三区免费看 | 99热1 | 99热这里只有精 | 人人人爽| 成人激情站 | 强行挺进白丝老师翘臀网站 | 亚洲人屁股眼子交1 | 丁香婷婷六月 | 国产一卡二卡 | 一区二区在线免费看 | 2020自拍偷拍| 久久99久久99精品中文字幕 | 日韩一区二区免费视频 | 女厕厕露p撒尿八个少妇 | 欧美性大交 | 久久久久久福利 | 日本极品丰满ⅹxxxhd | 日韩影视在线 | 黄色一级大片在线免费看产 | 色屁屁一区二区三区 | av一区免费 | 中文字字幕在线中文乱码 | 国产毛片久久久久久国产毛片 | 91av视频网| 国产激情av一区二区三区 | 日本欧美一本 | 日韩操比 | 一区二区 中文字幕 | 欧洲精品视频在线观看 | 丰满人妻一区二区三区无码av | www.av72 | 特大黑人巨交吊性xx | 国产精品二区在线 | 在线尤物| 先锋资源一区 | 合欢视频污 | 日韩综合网| 激情黄色小视频 | 黄色片91| 久久视频在线看 | asian性开放少妇pics | 成人第一页 | 亚洲黄色a级片 | 91人人澡人人爽人人精品 | 国产乱子伦一区二区 | 无码少妇一级AV片在线观看 | 国产区精品视频 | 国精产品一区一区三区免费视频 | 巨乳免费观看 | 少妇人妻偷人精品无码视频 | 日本高清视频在线 | 一本色道久久88综合无码 | 精品深夜av无码一区二区老年 | 伊人久综合 | 噜噜噜久久久 | 日本91av| 伊人97| 无码人妻精品一区二区三区在线 |