zoukankan      html  css  js  c++  java
  • POJ 1151 扫描线 线段树

    题意:给定平面直角坐标系中的N个矩形,求它们的面积并。

    题解:建立一个四元组(x,y1,y2,k).(假设y1<y2)用来储存每一条线,将每一条线按x坐标排序。记录所有的y坐标以后排序离散化。离散化之后线段树的第i个叶子节点储存的是y[i+1]-y[i].

    这里的线段树用的是一个不用下传延迟标记的做法(仅限这一类题)。线段树的每一个节点维护length(这个节点的子节点覆盖的长度)和cnt(这个节点代表的线段[l,r]所覆盖的次数)。

    任意一个区间都可以被线段树划分成O(logn)个子区间,我们把这些节点的cnt值加上1或减去1。

    在修改任意一个节点的cnt时或者向上维护信息的时候,如果这个节点的cnt>0,则这个节点所代表的区间覆盖的长度是y[r+1]-y[l],否则是子节点的长度和。

    代码:

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<map>
    using namespace std;
    map<double,int> mp;
    const int maxn=200010;
    struct ST{
    	int l,r,cnt;
    	double length;
    }t[4*maxn];
    struct node{
    	double x,y1,y2;
    	int k;
    	bool operator <(const node& rhs)const{
    		return x<rhs.x;
    	}
    }a[maxn];
    double b[maxn];
    void build(int p,int l,int r){
    	t[p].l=l,t[p].r=r;
    	t[p].cnt=0;
    	t[p].length=0;
    	if(l==r){
    		return;
    	}
    	int mid=(l+r)/2;
    	build(p*2,l,mid);
    	build(p*2+1,mid+1,r);
    }
    void maintain(int p){
    	if(t[p].l==t[p].r)t[p].length=0;
    	else t[p].length=t[p*2].length+t[p*2+1].length;
    }
    void change(int p,int l,int r,int k){
    	if(l<=t[p].l&&r>=t[p].r){
    		t[p].cnt+=k;
    		if(t[p].cnt>0){
    			t[p].length=b[t[p].r+1]-b[t[p].l];
    		}
    		else
    			maintain(p);
    		return;
    	}
    	int mid=(t[p].l+t[p].r)/2;
    	if(mid>=l)change(p*2,l,r,k);
    	if(mid<r)change(p*2+1,l,r,k);
    	if(t[p].cnt>0)t[p].length=b[t[p].r+1]-b[t[p].l];
    	else maintain(p); 
    }
    int main(){
    	int n,kase=0;
    	double x1,x2,y1,y2;
    	double ans=0;
    	while(~scanf("%d",&n)&&n){
    		ans=0;
    		mp.clear();
    		for(int i=1;i<=n;i++){
    			scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
    			a[i]=(node){x1,y1,y2,1};
    			a[i+n]=(node){x2,y1,y2,-1};
    			b[i]=y1,b[i+n]=y2;
    		}
    		sort(a+1,a+1+2*n);
    		sort(b+1,b+1+2*n);
    		int m=unique(b+1,b+1+2*n)-(b+1);
    		for(int i=1;i<=m;i++)
    			mp[b[i]]=i;
    		build(1,1,m-1);
    		for(int i=1;i<2*n;i++){
    			int l=mp[a[i].y1],r=mp[a[i].y2]-1;
    			change(1,l,r,a[i].k);
    			ans+=(a[i+1].x-a[i].x)*(t[1].length);
    		}
    		printf("Test case #%d
    Total explored area: %.2f
    
    ",++kase,ans);
    	}
    	return 0;
    } 
    

      

  • 相关阅读:
    python完成简单购物功能
    Java对字符串进行加密
    python完成留言板功能
    webpack4 学习
    webpack学习之 vue-cli3和4
    节点操作
    new 做了什么
    从url输入网址后发生什么
    防抖节流
    BFC原理和解决方案
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/9688471.html
Copyright © 2011-2022 走看看