• AcWing 247. 亚特兰蒂斯 (线段树,扫描线,离散化)


    • 题意:给你(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++<<'
    ';
    		cout<<"Total explored area: "<<fixed<<setprecision(2)<<res<<"
    
    ";
    
    	}
    
        return 0;
    }
    
  • 相关阅读:
    CentOS命令找不到
    Docker原理之rootfs
    Docker原理之Namespace
    Docker原理之Cgroups
    Docker目录
    Docker基本使用
    Linux命令之防火墙
    Linux命令目录
    Rancher之主机添加
    oracle-decode函数用法
  • 原文地址:https://www.cnblogs.com/lr599909928/p/14099348.html
Copyright © 2020-2023  润新知