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;
    } 
    

      

  • 相关阅读:
    关于datax的SqlServerReader 插件文档读取设置
    SQLyog13.1.1连接MySQL 8.0.19时出现的2058错误,加密方式因版本支持问题解决方法。
    mysql客户端版本太低的问题,应该是先改变加密方式再修改密码.client does not support authentication protocol requested by server consider upgrading mysql client
    IntelliJ IDEA的JavaWeb开发环境搭建
    异构数据源同步工具DataX Web用户手册(一、安装)
    datax安装
    Sql Server 中 根据具体的值 查找该值所在的表和字段
    1202. 交换字符串中的元素
    路径总和
    买卖股票的最佳时机(II)
  • 原文地址:https://www.cnblogs.com/pkgunboat/p/9688471.html
Copyright © 2011-2022 走看看