usaco Picture(离散化求线段周长)

本文介绍了一种通过离散化处理来计算多个矩形覆盖总面积边界的方法,利用水平和垂直扫描线技术,逐个更新覆盖区域的层数,并计算边界长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

usac前面有一题是递归求矩形覆盖面积的,学到不少东西

离散化 把所有矩形离散化(就是将整个平面分成许多“竖条”或“横条”,对其操作),每个矩形都由四条边组成,分为纵边和横边。对纵边和横边分别扫描一次,以横边为例:

  • 每个矩形的两条横边中,称下面的为始边,上面的为终边。
  • 把每条横边以纵坐标从小到大排序,如果纵坐标相同,则应把始边排到终边之前。
  • 依次枚举每条横边
    • 如果当前边为始边,则把这条边的横向的所有点j的层数增加1,即为level[j]++。如果层数由0变为了1,则这一点一定是边缘点,总周长ans++。
    • 如果当前边为终边,则把这条边的横向的所有点j的层数减少1,即为level[j]--。如果层数由1变为了0,则这一点一定是边缘点,总周长ans++。

同理按此方法扫描纵边,即可得到最后结果。


/*
ID:jinbo wu
TASK:picture
LANG:C++
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct node
{

    int s,e,y;
    bool ok;
}a[2][20500];
const int m=10000;
int ans=0;
int level[20500];
int n;
bool cmp(node a,node b)
{

    return a.y<b.y||(a.y==b.y&&a.ok);
}
void solve(int k)
{
    memset(level,0,sizeof(level));
    sort(a[k]+1,a[k]+n+1,cmp);
    for(int i=1;i<=n;i++)
    {

        if(a[k][i].ok)
        {

            for(int j=a[k][i].s;j<a[k][i].e;j++)
            {

                level[j]++;
                if(level[j]==1)
                    ans++;
            }
        }
        else
        {
            for(int j=a[k][i].s;j<a[k][i].e;j++)
            {

                level[j]--;
                if(level[j]==0)
                    ans++;
            }

        }
    }
}
int main()
{
    freopen("picture.in","r",stdin);
    freopen("picture.out","w",stdout);
    int x1,x2,y1,y2;
    cin>>n;
    for(int i=1;i<=n;i++)
    {

        cin>>x1>>y1>>x2>>y2;
        x1+=m,x2+=m,y1+=m,y2+=m;
        a[0][i*2-1].s=x1,a[0][i*2-1].e=x2,a[0][i*2-1].y=y1,a[0][i*2-1].ok=true;
        a[0][i*2].s=x1,a[0][i*2].e=x2,a[0][i*2].y=y2,a[0][i*2].ok=false;
        a[1][i*2-1].s=y1,a[1][i*2-1].e=y2,a[1][i*2-1].y=x1,a[1][i*2-1].ok=true;
        a[1][i*2].s=y1,a[1][i*2].e=y2,a[1][i*2].y=x2,a[1][i*2].ok=false;

    }
    n=n*2;
    solve(0);
    solve(1);
    cout<<ans<<endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值