HDU-1255 覆蓋的面積 (線段樹 求矩形覆蓋面積)
覆蓋的面積
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6458 Accepted Submission(s): 3286
Problem Description 給定平面上若干矩形,求出被這些矩形覆蓋過至少兩次的區域的面積.
Input 輸入資料的第一行是一個正整數T(1<=T<=100),代表測試資料的數量.每個測試資料的第一行是一個正整數N(1<=N<=1000),代表矩形的數量,然後是N行資料,每一行包含四個浮點數,代表平面上的一個矩形的左上角座標和右下角座標,矩形的上下邊和X軸平行,左右邊和Y軸平行.座標的範圍從0到100000.
注意:本題的輸入資料較多,推薦使用scanf讀入資料.
Output 對於每組測試資料,請計算出被這些矩形覆蓋過至少兩次的區域的面積.結果保留兩位小數.
Sample Input 2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1
Sample Output 7.63 0.00
#include <bits/stdc++.h> using namespace std; const int maxn = 1001; struct Xpoint{ double x, l, r; int v; bool operator < (const Xpoint& e){ return x < e.x; } }line[maxn << 1]; struct tree{ int cover; double len1, len2; }c[maxn << 4]; double y[maxn << 2]; void build(int o, int l, int r){ c[o].cover = c[o].len1 = c[o].len2 = 0; if(l == r - 1) return; int mid = l + r >> 1; build(o << 1, l, mid); build(o << 1 | 1, mid, r); } void pushup(int o, int l, int r){ if(c[o].cover > 0){ c[o].len1 = y[r] - y[l]; } else if(l == r - 1){ c[o].len1 = 0; } else{ c[o].len1 = c[o << 1].len1 + c[o << 1 | 1].len1; } if(c[o].cover > 1){ c[o].len2 = y[r] - y[l]; } else if(l == r - 1){ c[o].len2 = 0; } else if(c[o].cover == 1){ c[o].len2 = c[o << 1].len1 + c[o << 1 | 1].len1; //如果當前被完全覆蓋了一層,那麼不連續的子區間就是第二層覆蓋 } else c[o].len2 = c[o << 1].len2 + c[o << 1 | 1].len2; } void add(int o, int l, int r, int L, int R, int v){ if(l >= R || r <= L) return; if(l >= L && r <= R){ c[o].cover += v; pushup(o, l, r); return; } int mid = l + r >> 1; add(o << 1, l, mid, L, R, v); add(o << 1 | 1, mid, r, L, R, v); pushup(o, l, r); } int main(){ int n, T; scanf("%d", &T); double x1, x2, y1, y2; while(T--){ scanf("%d", &n); int tot = 0; for(int i = 1; i <= n; ++i){ scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2); line[++tot].x = x1; line[tot].l = y1; line[tot].r = y2; line[tot].v = 1; y[tot] = y1; line[++tot].x = x2; line[tot].l = y1; line[tot].r = y2; line[tot].v = -1; y[tot] = y2; } build(1, 1, tot); sort(y + 1, y + 1 + tot); sort(line + 1, line + 1 + tot); double ans = 0; for(int i = 1; i < tot; ++i){ y1 = lower_bound(y + 1, y + 1 + tot, line[i].l) - y; y2 = lower_bound(y + 1, y + 1 + tot, line[i].r) - y; add(1, 1, tot, y1, y2, line[i].v); ans += c[1].len2 * (line[i + 1].x - line[i].x); } printf("%.2lf\n", ans); } } /* 題意: 1000個矩形,座標範圍1e5,求所有矩形的總覆蓋面積。 思路: 我們把y軸對映到線段樹上,離散化一下,按照x的座標從小到大依次處理所有矩形的平行於y軸的邊。 每一個矩形x座標小的邊表示後面這個區域是被覆蓋的,直到遇到x大的邊結束。那麼我們對於所有矩形 左邊的邊,我們講其加到線段樹的區間上,這樣每處理一條邊,區間上被覆蓋的區間長度可以計算出來, 即這一段y軸的區域是被覆蓋的,再利用x算一下這一段的面積。一直處理完所有面積即可。 這一題需要主要的是需要維護兩次覆蓋,計算覆蓋區間時需要分類討論一下。 */
相關推薦
HDU-1255 覆蓋的面積 (線段樹 求矩形覆蓋面積)
覆蓋的面積 Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6458 Accepted Submiss
Hdu 1255 覆蓋的面積 線段樹+矩形面積並
繼續面積並學習中。。。(線段樹解決) 題意:給定平面上若干矩形,求出被這些矩形覆蓋過至少兩次的區域的面積 思路:其實跟求矩形面積並的思想是一樣的,只不過在update裡做了一點修改,矩形面積並只需要求至少覆蓋一次的面積,而這題是至少覆蓋兩次的面積,稍微做點修改就可以了 一樣
hdu-1255(線段樹求面積並)模板
題目連結:傳送門 思路: (1)建立線段的資訊,每個線段儲存l到r的線段的x位置和y的起始點與終點。 建立線段樹的節點資訊,每個節點代表一個區間的資訊,x表示區間的橫座標的位置,l,r表示縱座標的範圍,flag表示是否標記過,cover表示線段的覆蓋次數。 (2)先將y的位置按照從小到大排序,再將邊按
HDU 5592 ZYB's Premutation (線段樹求逆序對)
題意 給你一組從1到n的排列,表示的是你當前所擁有的逆序對數,現在讓你重新還原這個排列。 思路 我們知道 [1⋅⋅⋅i] [ 1 ·
hdu 1556 塗氣球 線段樹(區間更新~對區間[x,y]更新,求任意節點被更新的次數)
Color the ball Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 29526 &nbs
hdu Minimum Inversion Number(線段樹求逆序數有關問題的一個小歸納)
Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4904
hdu 1394(線段樹求逆序數)
題意描述:給你一個有0--n-1數字組成的序列,然後進行這樣的操作,每次將最前面一個元素放到最後面去會得到一個序列,那麼這樣就形成了n個序列,那麼每個序列都有一個逆序數,找出其中最小的一個輸出! 分析:其實只需求出一個序列的逆序數即可,一位第i+1個序列的逆序數為第i
hdu 1542 線段樹之掃描線之面積並
題意:給你n個矩形,求它們的面積,重複的不重複計算 思路:用線段樹的掃描線完成,將X座標離散化後,從下到上掃描矩形,進行各種處理,看程式碼註釋把#include <stdio.h> #include <string.h> #include <
hdu 3333 Turing Tree(線段樹)
target vector nac ++ uil sim con wrap pro 題目鏈接:hdu 3333 Turing Tree 題目大意:給定一個長度為N的序列。有M次查詢,每次查詢l。r之間元素的總和,同樣元素僅僅算一次。 解題思路:漲姿勢了,線段樹的一
HDU 3016 Man Down(線段樹)
mes pri microsoft sun lan 遊戲 important -m acm HDU 3016 Man Down 題目鏈接 題意:是男人就下100層的遊戲的簡單版,每次僅僅能從兩端下落。求落地最大血量 思路:利用線段樹能夠處理出每一個線段能來自哪幾
HDU 4902 Nice boat 線段樹+離線
uil lin ack long wap math.h 離線 線段 str 據說暴力也過了。還傻逼地寫了這麽長。。。 #include <stdio.h> #include <string.h> #include <ma
第四場 hdu 6070 Dirt Ratio (線段樹+二分)
math sizeof i++ 樹節點 size iostream col 個數 ext http://acm.hdu.edu.cn/showproblem.php?pid=6070 題目大意:給出的序列上的數代表顏色,求子序列中不同數字的個數X與子序列長度Y中,X/Y
hdu1166 敵兵布陣(線段樹 求區間和 更新點)
popu [0 node align 任務 lar bmi bottom tdi 敵兵布陣 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others
HDU 6155 Subsequence Count 線段樹維護矩陣
input ans ons tom thml other family 卡常 子序列 Subsequence Count Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 256000/256000 K (J
hdu 3397 Sequence operation 線段樹 區間更新 區間合並
clas cnblogs -- std hdu 查詢 namespace || 兩個 題意: 5種操作,所有數字都為0或1 0 a b:將[a,b]置0 1 a b:將[a,b]置1 2 a b:[a,b]中的0和1互換 3 a b:查詢[a,b]中的1的數量
hdu 1540 Tunnel Warfare 線段樹 區間合並
freopen uil spa war hdu pri har pre build 題意: 三個操作符 D x:摧毀第x個隧道 R x:修復上一個被摧毀的隧道,將摧毀的隧道入棧,修復就出棧 Q x:查詢x所在的最長未摧毀隧道的區間長度。 1.如果當前區間全是未
hdu 6183 Color it(線段樹)
php 每次 alt using update -a pac flag aps 題目鏈接:hdu 6183 Color it 題意: 在一個二維平面上有n個操作。 1. x y c 在(x,y)這點上添加一個顏色c。 2. x y1 y2 詢問二維平面[1,x]~[y1,y
HDU.6155.Subsequence Count(線段樹 矩陣)
open har acm 就是 details efi ron git %d 題目鏈接 首先考慮詢問[1,n]怎麽做 設 f[i][0/1]表示[1,i]以0/1結尾的不同子序列個數 則\(if(A[i]) f[i][1] = f[i-1][0] + f[i-1][1] +
線段樹求逆序對
std con pac clu can -m cnblogs amp ons 思路: 離散化變成一個1-n的數組表示每個數的排名,然後按順序插入各個數排名,並且查詢比它排名大的數的個數。 這個離散化方法還是比較好的,思維難度和代碼難度都比較小。 #include <
HDU - 6315 Naive Operations (線段樹+思維) 2018 Multi-University Training Contest 2
延遲 給定 要求 lse define 位置 efi operation date 題意:數量為N的序列a和b,a初始全為0,b為給定的1-N的排列。有兩種操作:1.將a序列區間[L,R]中的數全部+1;2.查詢區間[L,R]中的 ∑?ai/bi?(向下取整) 分析:對於一