蓝桥杯 奇偶覆盖 模拟

题目描述

在平面内有一些矩形,它们的两条边都平行于坐标轴。

我们称一个点被某个矩形覆盖,是指这个点在矩形的内部或者边界上。

请问,被奇数个矩形覆盖和被偶数 (≥ 2)(≥2) 个矩形覆盖的点的面积分别是多少?

输入描述

输入的第一行包含一个整数 nn,表示矩形的个数。

接下来 nn 行描述这些矩形,其中第 ii 行包含四个整数 l_i,b_i, r_i, t_ili​,bi​,ri​,ti​,表示矩形的两个对角坐标分别为 (l_i, b_i),(r_i, t_i)(li​,bi​),(ri​,ti​)。

其中,1 ≤ n ≤ 10^5, 0 ≤ l_i < r_i ≤ 10^9, 0 ≤ b_i < t_i ≤ 10^91≤n≤105,0≤li​<ri​≤109,0≤bi​<ti​≤109。

输出描述

输出两行。

第一行包含一个整数,表示被奇数个矩形覆盖的点的面积。

第二行包含一个整数,表示被偶数 (≥ 2)(≥2) 个矩形覆盖的点的面积。

输入输出样例

示例 1

输入

3
1 1 3 3
2 2 4 4
3 3 5 5

输出

8
2

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M

精选项目课程_IT热门课程_蓝桥云课课程 - 蓝桥云课

==================================

只通过了样例、提交检测未通过?为什么呢?

做法:模拟

import java.util.Scanner;
// 1:无需package
// 2: 类名必须Main, 不可修改

public class Main {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        // 在此输入您的代码...
        int n = scan.nextInt();
        int[][] rectangles = new int[n][4];
        int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE,
                maxX = Integer.MIN_VALUE, maxY = Integer.MIN_VALUE;
        for (int i = 0; i < n; i++) {
            rectangles[i][0] = scan.nextInt();
            rectangles[i][1] = scan.nextInt();
            rectangles[i][2] = scan.nextInt();
            rectangles[i][3] = scan.nextInt();
            int x1 = rectangles[i][0], y1 = rectangles[i][1], x2 = rectangles[i][2], y2 = rectangles[i][3];
            minX = Math.min(minX, x1);
            minY = Math.min(minY, y1);
            maxX = Math.max(maxX, x2);
            maxY = Math.max(maxY, y2);
        }
        // 注意题目说的是面积
        int[][] pos = new int[maxX][maxY];
        int cntJ = 0, cntO = 0;
        // 填充面积
        for (int i = 0; i < n; i++) {
            int x1 = rectangles[i][0], y1 = rectangles[i][1], x2 = rectangles[i][2], y2 = rectangles[i][3];
            for (int x = x1; x < x2; x++) {
                for (int y = y1; y < y2; y++) {
                    pos[x][y]++;
                }
            }
        }
        // 奇偶查看
        for (int i = minX; i < maxX; i++) {
            for (int j = minY; j < maxY; j++) {
                if (pos[i][j] == 0) continue;
                if (pos[i][j] % 2 == 1) cntJ++;
                else if (pos[i][j] != 0) cntO++;
            }
        }
        System.out.println(cntJ);
        System.out.println(cntO);
        scan.close();
    }
}

C++代码(题解提供的)

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
typedef long long ll; 
using namespace std;
#define int long long
const int N = 300010;
vector<int>v;
struct Seg{
    int x;
    int l;
    int r;
    int k;
    bool operator<(const Seg&w)const
    {
        if(x!=w.x)
        return x<w.x;
        return k>w.k;
    }    
}seg[N<<1];

struct node{
    int l;
    int r;
    int len1;
    int len2;
    int cnt;
}tr[N<<2];
int get(int x)
{
    return lower_bound(v.begin(),v.end(),x)-v.begin();
}
void pushup(int u)
{
    if(tr[u].cnt)
    {
        if(tr[u].cnt&1)
        {
            tr[u].len1=tr[u<<1].len2+tr[u<<1|1].len2;
            tr[u].len2=tr[u<<1].len1+tr[u<<1|1].len1;
            tr[u].len1+=v[tr[u].r+1]-v[tr[u].l]-tr[u].len1-tr[u].len2;
        }
        else
        {
            tr[u].len1=tr[u<<1].len1+tr[u<<1|1].len1;
            tr[u].len2=tr[u<<1].len2+tr[u<<1|1].len2;
            tr[u].len2+=v[tr[u].r+1]-v[tr[u].l]-tr[u].len1-tr[u].len2;
        }
    }
    else if(tr[u].l!=tr[u].r)
    {
        tr[u].len1=tr[u<<1].len1+tr[u<<1|1].len1;
        tr[u].len2=tr[u<<1].len2+tr[u<<1|1].len2;
    }
    else
    {
        tr[u].len1=tr[u].len2 = 0;
    }
}
void build(int u,int l,int r)
{
    tr[u]  ={l,r};
    if(l==r)
    return ;
    int mid=l+r>>1;
    build(u<<1,l,mid);
    build(u<<1|1,mid+1,r);
    
    
}
void mdf(int u,int l,int r,int k){
    if(tr[u].l>=l && tr[u].r<=r)
    {
        tr[u].cnt+=k;
        pushup(u);
        return ;
    }
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)    mdf(u<<1,l,r,k);
    if(r>mid)    mdf(u<<1|1,l,r,k);
    pushup(u);
}
signed main()
{
    ios;
    int n;
    ll res1=0;
    ll res2=0;
    int cnt=0;
    cin >> n;
    for(int i=1;i<=n;i++)
    {
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        v.push_back(b);
        v.push_back(d);
        seg[cnt++]={a,b,d,1};
        seg[cnt++]={c,b,d,-1};
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    build(1,0,(int)v.size()-2);
    sort(seg,seg+cnt);
//    return 0;
    for(int i=0;i<cnt;i++)
    {
        if(i)
        {
            res1+=1ll*(seg[i].x-seg[i-1].x)*tr[1].len1;
            res2+=1ll*(seg[i].x-seg[i-1].x)*tr[1].len2;
        }
        mdf(1,get(seg[i].l),get(seg[i].r)-1,seg[i].k);
    }
        cout<<res1<<endl<<res2<<endl;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值