概述
Codeforces 610D
题目链接:
http://blog.csdn.net/julyana_lin/article/details/7834653
题意:
给n个矩形,宽度均为1,与x或者y中一个轴平行。
矩形可能有覆盖。
求所有矩形覆盖后的面积和。
思路:
有map乱弄的做法,以下采用矩阵面积并。
矩阵面积并 = 线段树 + 扫描线 + 离散化
把矩形分成下边和上边,下边进入事件,上边离开事件。
每条边左右端点进行离散化,具体实现用map和数组都可以。
维护线段树,线段树中每个点的坐标为离散化以后的坐标。
线段树的每个节点存两个值,一个是覆盖的层数,一个是返回的和。
注意:update时为update(L,R-1…),push_up时中第二个条件分支为idx[R+1] - idx[L]
这个下标是表示端点离散化以后,分割成的一个一个小线段的这个线段的左端点。。。更 新的时候也是同一个道理。。。这样表示可以避免由于线段树更新中一些线段没有算到的 情况,比如[1,4]分割成[1,2],[3,4],如果不这样更新就会少算[2,3]这条线段。
本题中我把每个点处理成以它为左下角的小单位矩形。
源码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int MAXN = 1e6 + 5;
#define LL long long
struct FenwickTree
{
int L, R;
LL sum;
int val; ///times for overlap
}tree[MAXN * 4];
map<int,int>mx, my; ///原始坐标转化成离散化的坐标
map<int,int>idx, idy; ///离散化的坐标转化成原始坐标
int tempx[MAXN * 4], tempy[MAXN * 4];
int cntx, cnty; ///离散后x坐标和y坐标总个数,从1开始
void build(int o, int L, int R)
{
tree[o].L = L, tree[o].R = R, tree[o].val = 0, tree[o].sum = 0;
if(L == R) return;
int mid = (L + R) >> 1;
if(mid >= L) build(o * 2, L, mid);
if(mid < R) build(o * 2 + 1, mid + 1, R);
}
void push_up(int o)
{
if(tree[o].val) tree[o].sum = idx[tree[o].R+1] - idx[tree[o].L]; ///注意此处
else if(tree[o].L == tree[o].R) tree[o].sum = 0;
else tree[o].sum = tree[o * 2].sum + tree[o * 2 + 1].sum;
}
void update(int o, int L, int R, int val)
{
// system("pause");
if(tree[o].L >= L && tree[o].R <= R){
tree[o].val += val;
}
else{
int mid = (tree[o].L + tree[o].R) >> 1;
if(mid >= L) update(o * 2, L, R, val);
if(mid < R) update(o * 2 + 1, L, R, val);
}
push_up(o);
// if(tree[o].L == tree[o].R){
// printf("L = %d, idx[tree[o].R] = %d, idx[tree[o].L-1]=%dn", tree[o].L, idx[tree[o].R], idx[tree[o].L-1]);
// }
// printf("o = %d, val = %d, tree[o].L = %d, tree[o].R = %d, tree[o].sum = %I64dn", o, val, tree[o].L, tree[o].R, tree[o].sum);
}
struct D
{
int x1, y1, x2, y2;
}d[MAXN];
struct E
{
int mark;
int L, R, y;
int op;
E(){}
E(int _L, int _R, int _y, int _op){L = _L, R = _R, y = _y, op = _op;}
}e[MAXN * 4];
bool cmp(D a, D b){return a.y1 < b.y1;}
bool cmp2(E a, E b)
{
if(a.y == b.y) return a.op < b.op;
else return a.y < b.y;
}
int main()
{
int n;
while(scanf("%d", &n) != EOF){
mx.clear(); my.clear();
idx.clear(); idy.clear();
int tempcnt = 0;
for(int i = 0 ; i < n ; i++){
scanf("%d%d%d%d", &d[i].x1, &d[i].y1, &d[i].x2, &d[i].y2);
if(d[i].x1 > d[i].x2) swap(d[i].x1, d[i].x2);
if(d[i].y1 > d[i].y2) swap(d[i].y1, d[i].y2);
d[i].x2++, d[i].y2++;
// printf("i = %d, x1 = %d, x2 = %d, y1 = %d, y2 = %dn", i, d[i].x1, d[i].x2, d[i].y1, d[i].y2);
tempx[tempcnt] = d[i].x1, tempy[tempcnt++] = d[i].y1;
tempx[tempcnt] = d[i].x2, tempy[tempcnt++] = d[i].y2;
}
sort(tempx, tempx + tempcnt);
sort(tempy, tempy + tempcnt);
cntx = cnty = 0;
for(int i = 0 ; i < tempcnt ; i++){
if(mx[tempx[i]] == 0) mx[tempx[i]] = ++cntx, idx[cntx] = tempx[i];
if(my[tempy[i]] == 0) my[tempy[i]] = ++cnty, idy[cnty] = tempy[i];
}
build(1, 1, cntx);
// sort(d, d + n, cmp);
for(int i = 0 ; i < n ; i++){
e[i * 2] = E(mx[d[i].x1], mx[d[i].x2], my[d[i].y1], 1), e[i * 2].mark = i;
e[i * 2 + 1] = E(mx[d[i].x1], mx[d[i].x2], my[d[i].y2], -1), e[i * 2 + 1].mark = i;
}
LL ans = 0;
sort(e, e + 2 * n, cmp2);
for(int i = 0 ; i < 2 * n ; i++){
update(1, e[i].L, e[i].R - 1, e[i].op);
if(i < 2 * n - 1)
ans += tree[1].sum * (idy[e[i + 1].y - e[i].y); ///注意此处顺序
}
printf("%I64dn", ans);
}
return 0;
}
最后
以上就是鲜艳悟空为你收集整理的Codeforces 610D 矩形面积并的全部内容,希望文章能够帮你解决Codeforces 610D 矩形面积并所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复