题目描述
在平面内有一些矩形,它们的两条边都平行于坐标轴。
我们称一个点被某个矩形覆盖,是指这个点在矩形的内部或者边界上。
请问,被奇数个矩形覆盖和被偶数 (≥ 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
==================================
只通过了样例、提交检测未通过?为什么呢?
做法:模拟
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;
}