AcWing 247. 亞特蘭蒂斯 (線段樹,掃描線,離散化)
阿新 • • 發佈:2020-12-07
- 題意:給你\(n\)個矩形,求矩形並的面積.
- 題解:我們建立座標軸,然後可以對矩形的橫座標進行排序,之後可以遍歷這些橫座標,這個過程可以想像成是一條線從左往右掃過x座標軸,假如這條線是第一次掃過矩形的寬(長)的話,我們就可以在\(y\)軸上對應的區間打上標記,每次列舉的面積就是當前橫座標和上次橫座標的差值乘上目前\(y\)軸上所有打上標記的區間長度\((seg[i].x-seg[i-1].x)*tr[1].len\),y軸上的區間情況我們可以通過線段樹來維護.
- 程式碼:
#include <bits/stdc++.h> #define ll long long #define fi first #define se second #define pb push_back #define me memset #define rep(a,b,c) for(int a=b;a<=c;++a) #define per(a,b,c) for(int a=b;a>=c;--a) const int N = 1e6 + 10; const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; using namespace std; typedef pair<int,int> PII; typedef pair<ll,ll> PLL; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} ll lcm(ll a,ll b) {return a/gcd(a,b)*b;} struct Segment{ double x,y1,y2; int k; bool operator < (const Segment & tmp) const { return x<tmp.x; } }seg[N*2]; struct Node{ int l,r; int cnt; double len; }tr[8*N]; vector<double> ys; void push_up(int u){ if(tr[u].cnt) tr[u].len=ys[tr[u].r+1]-ys[tr[u].l]; else if(tr[u].l!=tr[u].r){ tr[u].len=tr[u<<1].len+tr[u<<1|1].len; } else tr[u].len=0; //葉子節點並且沒有標記 } void build(int u,int l,int r){ tr[u].l=l; tr[u].r=r; if(l==r) return; int mid=(l+r)>>1; build(u<<1,l,mid); build(u<<1|1,mid+1,r); } void modify(int u,int l,int r,int k){ if(tr[u].l>=l && tr[u].r<=r){ tr[u].cnt+=k; push_up(u); } else{ int mid=(tr[u].l+tr[u].r)>>1; if(l<=mid) modify(u<<1,l,r,k); if(r>mid) modify(u<<1|1,l,r,k); push_up(u); } } int main() { ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); int n; int T=1; while(cin>>n){ if(n==0) break; ys.clear(); int j=0; rep(i,0,n-1){ double x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; seg[j++]={x1,y1,y2,1}; seg[j++]={x2,y1,y2,-1}; ys.pb(y1),ys.pb(y2); } sort(ys.begin(),ys.end()); ys.erase(unique(ys.begin(),ys.end()),ys.end()); build(1,0,ys.size()-2); sort(seg,seg+2*n); double res=0; rep(i,0,2*n-1){ //列舉橫座標 tr[1].len就表示縱座標區間之和 if(i>0) res+=tr[1].len*(seg[i].x-seg[i-1].x); int pos1=lower_bound(ys.begin(),ys.end(),seg[i].y1)-ys.begin(); int pos2=lower_bound(ys.begin(),ys.end(),seg[i].y2)-ys.begin(); modify(1,pos1,pos2-1,seg[i].k); } cout<<"Test case #"<<T++<<'\n'; cout<<"Total explored area: "<<fixed<<setprecision(2)<<res<<"\n\n"; } return 0; }