zoukankan      html  css  js  c++  java
  • 51nod 1206:Picture 求覆盖周长

    题目来源: IOI 1998
    基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题
     收藏
     关注
    给出平面上的N个矩形(矩形的边平行于X轴和Y轴),求这些矩形组成的所有多边形的周长之和。

    例如:N = 7。(矩形会有重叠的地方)。

    合并后的多边形:


    多边形的周长包括里面未覆盖部分方块的周长。
    Input
    第1行:1个数N。(2 <= N <= 50000)
    第2 - N + 1行,每行4个数,中间用空格分隔,分别表示矩形左下和右上端点的坐标。(-1000000 <= X[i], Y[i] <= 1000000)
    Output
    输出多边形的周长。
    Input示例
    7
    -15 0 5 10
    -5 8 20 25
    15 -4 24 14
    0 -6 16 4
    2 15 10 22
    30 10 36 20
    34 0 40 16
    Output示例
    228

    最近真的是被线段树扫描线搞得心力憔悴,刚刚才把poj上面求面积的弄懂,然后又遇到了求周长的。

    思想和求面积是差不多的,变化就是多了一个line,就是当前的线段树分成了几段,这个在求面积的时候不会用到,但是求周长会用到。比如[1,1][2,2]就只有1段,[1,1][3,3]在线段树[1,3]的节点中就分成了两段。

    第二点就是注意

    tree[root].interval=tree[root*2+1].interval+tree[root*2+2].interval-tree[root*2+1].Rcover*tree[root*2+2].Lcover;

    计算分成了多少块 是左子树的分块数+右子树的分块数,为了防止左子树的右边和右子树的左边连在一块,所以还要把这部分扣掉。

    第三点就是注意排序,如果在x值相等的情况下,要将入边放在前面先处理,出边后处理。

    代码:

    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <vector>
    #include <string>
    #include <cstring>
    #pragma warning(disable:4996)
    using namespace std;
    
    struct li
    {
    	int x,y1,y2;
    	int bLeft;
    }line[500005];
    
    int y[500005];
    int n;
    
    struct no
    {
    	int L;
    	int R;
    	int cover;
    	int Lcover;
    	int Rcover;
    	int interval;
    	int m;
    }tree[500005];
    
    void buildtree(int root,int L,int R)
    {
    	tree[root].L=L;
    	tree[root].R=R;
    	tree[root].cover=0;
    	tree[root].Lcover=0;
    	tree[root].Rcover=0;
    	tree[root].interval=0;
    	tree[root].m=0;
    
    	if(L!=R)
    	{
    		int mid = (L+R)/2;
    		buildtree(root*2+1,L,mid);
    		buildtree(root*2+2,mid+1,R);
    	}
    }
    
    void insert(int root,int L,int R)
    {
    	if(tree[root].L==L&&tree[root].R==R)
    	{
    		tree[root].cover++;
    		tree[root].m = y[R+1]-y[L];
    		tree[root].Lcover=1;
    		tree[root].Rcover=1;
    		tree[root].interval=1;
    		return;
    	}
    	else
    	{
    		int mid = (tree[root].L + tree[root].R)/2;
    		if(R<=mid)
    		{
    			insert(root*2+1,L,R);
    		}
    		else if(L>=mid+1)
    		{
    			insert(root*2+2,L,R);
    		}
    		else
    		{
    			insert(root*2+1,L,mid);
    			insert(root*2+2,mid+1,R);
    		}
    	}
    	if(tree[root].cover==0)
    	{
    		tree[root].m = tree[root*2+1].m +tree[root*2+2].m;
    		tree[root].Lcover=tree[root*2+1].Lcover;
    		tree[root].Rcover=tree[root*2+2].Rcover;
    		tree[root].interval=tree[root*2+1].interval+tree[root*2+2].interval-tree[root*2+1].Rcover*tree[root*2+2].Lcover;
    	}
    }
    
    void dele(int root,int L,int R)
    {
    	if(tree[root].L==L&&tree[root].R==R)
    	{
    		tree[root].cover--;
    	}
    	else
    	{
    		int mid = (tree[root].L + tree[root].R)/2;
    		if(R<=mid)
    		{
    			dele(root*2+1,L,R);
    		}
    		else if(L>=mid+1)
    		{
    			dele(root*2+2,L,R);
    		}
    		else
    		{
    			dele(root*2+1,L,mid);
    			dele(root*2+2,mid+1,R);
    		}
    	}
    	if(tree[root].cover<=0&&tree[root].L==tree[root].R)
    	{
    		tree[root].m=0;
    		tree[root].Lcover=0;
    		tree[root].Rcover=0;
    		tree[root].interval=0;
    	}
    	else if(tree[root].cover<=0)
    	{
    		tree[root].m = tree[root*2+1].m +tree[root*2+2].m;
    		tree[root].Lcover=tree[root*2+1].Lcover;
    		tree[root].Rcover=tree[root*2+2].Rcover;
    		tree[root].interval=tree[root*2+1].interval+tree[root*2+2].interval-tree[root*2+1].Rcover*tree[root*2+2].Lcover;
    	}
    }
    
    bool cmp(struct li line1, struct li line2)
    {
    	if (line1.x == line2.x)
    		return line1.bLeft > line2.bLeft;
    	return (line1.x < line2.x);
    }
    
    template <class F,class T>  
    F bin_search(F s,F e,T val)  
    {  
    	F L = s;  
    	F R = e-1;  
    
    	while(L<=R)  
    	{  
    		F mid = L + (R-L)/2;  
    		if(!(*mid<val || val < *mid))  
    		{  
    			return mid;  
    		}  
    		else if(val < *mid)  
    		{  
    			R = mid -1;  
    		}  
    		else  
    		{  
    			L= mid + 1;  
    		}  
    	}  
    }  
    
    int main()
    {	
    	//freopen("i.txt","r",stdin);
    	//freopen("o.txt","w",stdout);
    
    	int i,x1,x2,y1,y2,yc,lc;
    	scanf("%d",&n);
    
    	yc=0;
    	lc=0;
    	for(i=0;i<n;i++)
    	{
    		scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
    		y[yc++]=y1;
    		y[yc++]=y2;
    
    		line[lc].x=x1;
    		line[lc].y1=y1;
    		line[lc].y2=y2;
    		line[lc].bLeft = 1;
    		lc++;
    
    		line[lc].x=x2;
    		line[lc].y1=y1;
    		line[lc].y2=y2;
    		line[lc].bLeft = 0;
    		lc++;
    	}
    	sort(line,line+lc,cmp);
    	sort(y,y+yc);
    	yc=unique(y,y+yc)-y;
    
    	buildtree(0,0,yc-1-1);
    	int preme=0;
    	int now_m=0;
    	int now_line=0;
    	for(i=0;i<=lc-1;i++)
    	{
    		int L=bin_search(y,y+yc,line[i].y1)-y;  
    		int R=bin_search(y,y+yc,line[i].y2)-y;  
    
    		if(line[i].bLeft)  
    		{  
    			insert(0,L,R-1);  
    		}  
    		else  
    		{  
    			dele(0,L,R-1);  
    		}
    		if(i>=1)
    			preme += 2*now_line*(line[i].x-line[i-1].x);
    		preme += abs(tree[0].m-now_m);
    		now_m=tree[0].m;
    		now_line=tree[0].interval;
    	}
    	printf("%d
    ",preme);
    	//system("pause");
    	return 0;
    }


    版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    mysql查看所有的数据库
    查看/杀死mysql进程
    PL/SQL 保存页面布局
    Linux 隐藏文件和目录,显示隐藏的文件和目录
    win10插入U盘多显示了一个盘符
    Linux安装rz和sz命令
    PL/SQL链接Oracle出现乱码
    解决Tomcat: Can't load IA 32-bit .dll on a AMD 64-bit platform问题
    Eclipse集成Tomcat的配置步骤实例
    搭建Eclipse+MyEclipse开发环境
  • 原文地址:https://www.cnblogs.com/lightspeedsmallson/p/4899536.html
Copyright © 2011-2022 走看看