1 条题解

  • 0
    @ 2025-4-17 16:20:43

    题意:给出若干矩形的对角线的坐标;求出矩形面积并; 解题思路:我们首先想到扫描线算法,利用计算机只能处理离散量的特性,所以我们将矩形离散成事件点:矩形的左,右两边的横坐标,纵坐标,另外,纵坐标是需要离散化的;扫描线第一次扫描到左边时,将这一段长度加入用线段树维护的数组中,这样可以保证不遗漏任何面积,也不会重复计算面积,扫到右边时,删除线段; 代码:

    #include<stdio.h>
    #include<memory.h>
    #include<algorithm>
    #define MAXN 11000
    using namespace std;
    struct Rect{
    	long long x1,x2,y1,y2;
    };
    struct event{
    	long long x,y1,y2;
    	long long add;
    };
    struct segtree{
    	long long count,total;//count表示当前线段树中还有多少个矩形,total表示扫描线的长度; 
    };
    long long n=0;
    Rect rect[MAXN];
    event evi[2*MAXN];
    segtree tree[2*MAXN];
    long long id[2*MAXN];
    bool cmp(event a,event b)
    {
    	return a.x<b.x;
    }
    void up(long long i,long long lb,long long rb)
    {
    	tree[i].total=tree[i*2].total+tree[i*2+1].total;
    	if(tree[i].count)
    	tree[i].total=abs(id[rb]-id[lb]);
    }
    void ins(long long i,long long lb,long long rb,long long a,long long b,long long k)//线段树更新 
    {
    	if(lb==a&&rb==b)
    	{
    		tree[i].count+=k;
    		up(i,lb,rb);
    		return;
    	}
    	long long med=(lb+rb)/2;
    	if(b<=med)
    	ins(2*i,lb,med,a,b,k);
    	else if(a>=med)
    	ins(2*i+1,med,rb,a,b,k);
    	else
    	{
    		ins(2*i,lb,med,a,med,k);
    		ins(2*i+1,med,rb,med,b,k);
    	}
    	up(i,lb,rb);
    }
    long long area()
    {
    	for(long long i=0;i<n;i++)
    	{
    		id[i]=rect[i].y1;
    		id[i+n]=rect[i].y2;
    	}
    	sort(id,id+2*n);
    	for(long long i=0;i<2*n;i++)//离散化 
    	{
    		rect[i].y1=lower_bound(id,id+2*n,rect[i].y1)-id;
    		rect[i].y2=lower_bound(id,id+2*n,rect[i].y2)-id;
    	}
    	for(long long i=0;i<n;i++)
    	{
    		evi[i].add=1;
    		evi[i+n].add=-1;
    		evi[i].x=rect[i].x1;
    		evi[i+n].x=rect[i].x2;
    		evi[i].y1=evi[i+n].y1=rect[i].y1;
    		evi[i].y2=evi[i+n].y2=rect[i].y2;
    	}
    	sort(evi,evi+n*2,cmp);
    	long long ans=0;
    	for(long long i=0;i<2*n;i++)
    	{
    		if(i>0&&evi[i].x>evi[i-1].x)
    		ans+=(evi[i].x-evi[i-1].x)*tree[1].total;
    		long long a=min(evi[i].y1,evi[i].y2);
    		long long b=max(evi[i].y1,evi[i].y2);
    		ins(1,0,2*n-1,a,b,evi[i].add);
    	}
    	return ans;
    }
    int main()
    {
    	long long a,b,c,d,i=0;
    	bool flag;
    	while(1)
    	{
    		memset(tree,0,sizeof(tree));
    		memset(rect,0,sizeof(rect));
    		memset(evi,0,sizeof(evi));
    		memset(id,0,sizeof(id));
    		n=0;i=0;
    		flag=false;
    		while(1)
    		{
    			scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
    			if(a==-1&&!flag)
    			{
    				return 0;
    			}			
    			else if(a==-1)
    			break;
    			else
    			{
    				rect[i].x1=a;
    				rect[i].y1=b;
    				rect[i].x2=c;
    				rect[i++].y2=d;
    				n++;
    				flag=true;
    			}
    		}
    		printf("%lld\n",area());
    	}
    	return 0;
    }
    • 1

    信息

    ID
    390
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者