看数据范围像是个暴力,而且理论复杂度似乎可行,然后被卡了两个点。。。然后来了个乱搞的线段树+扫描线。。

3225: [Sdoi2008]立方体覆盖

Time Limit: 2 Sec Memory Limit: 128 MB

Submit: 102 Solved: 64

[Submit][Status][Discuss]

Description

  A君近日为准备省队选拔,特意进行了数据结构的专项训练。训练过程中就遇到了“矩形面积并”这道经典问题,即:给出N个各边与坐标轴平行(垂直)的矩形,求矩形覆盖的面积之和。A君按纵坐标建立线段树后按横坐标扫描计算,轻易AC了这道题,时间复杂度为O(NlogN)。

  为了强化训练,A君将问题推广到三维空间中,即:给出N个各棱与坐标轴平行(垂直)的立方体,求立方体覆盖的体积之和。为了简化问题,令立方体均退化为正立方体,用四元组(x, y, z, r)表示一个立方体,其中x, y, z为立方体的中心点坐标,r为中心点到立方体各个面的距离(即立方体高的一半)。

  这次可难住了A君,只好请你——未来的金牌——来帮助他了。

Input

  第一行是一个正整数N。

  以下N行每行四个整数x, y, z, r,由空格隔开。

Output

  共一个数,即覆盖的总体积。

Sample Input

3

0 0 0 3

1 –1 0 1

19 3 5 6

Sample Output

1944

HINT

对于 100% 的数据,1≤N≤100

对于 100% 的数据,-1000≤x, y, z≤1000,1≤r≤200

线段树+扫描线怎么搞非常容易,即确定一个轴离散另一个,然后分段扫描求面积求和即可。此题二维,可以同理。
直接写个二维的线段树(线段树套线段树)会舒服很多,可惜树套树不是很会,于是乱搞了个。。

于是我先枚举离散后的高,再次基础上控制满足条件的x,y。

利用扫描线的思想,把每一条竖边取出并按x从左到右快排,然后扫描。如果一条边是始边,把线段树中的y1–y2加1,否则把y1–y2减1。然后对于每一个不同的x,把线段树中覆盖层数大于1的个数*(x[i+1]-x[i])。

这个线段树的细节很多,比如线段树建立是l~mid,mid~r,然后叶子节点是l~l+1。

code:

#include<cstdio>
#include<algorithm>
using namespace std;
int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define maxn 1010
const int ff=1200; struct tre{int sum,del,l,r;}tree[210*2*16];
int x1[110],x2[110],y1[110],y2[110],z1[110],z2[110];
int tz,tZ,ty,tY;;
int Z[220],Y[220],z[220],y[220];
int n,t,tmp;
int ans=0;
struct data{int x,l,r,f;}xd[220];
int pp[2500];int to;
int L,R,F;int h,W; void build(int now,int l,int r)
{
tree[now].l=l,tree[now].r=r;
tree[now].sum=tree[now].del=0;
if (l==r || l+1==r) return;
int mid=(l+r)>>1;
build(now<<1,l,mid);
build(now<<1|1,mid,r);
} void insert(int now)
{
if (L<=tree[now].l && R>=tree[now].r)
{
if (!F) tree[now].del++,tree[now].sum=y[tree[now].r]-y[tree[now].l]; else
if (!(--tree[now].del)) tree[now].sum=(tree[now].l+1>=tree[now].r)?0:tree[now<<1].sum+tree[now<<1|1].sum;
return;
}
int mid=(tree[now].l+tree[now].r)>>1;
if (L<mid) insert(now<<1);
if (R>mid) insert(now<<1|1);
if (!tree[now].del) tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
} bool cmp(data a,data b)
{
if (a.x!=b.x) return a.x<b.x;
return !a.f&&b.f;
} int main()
{
n=read();
for (int i=1; i<=n; i++)
{
int xx=read(),yy=read(),zz=read(),r=read();
x1[i]=xx-r;x2[i]=xx+r;
y1[i]=yy-r;y2[i]=yy+r;
z1[i]=zz-r;z2[i]=zz+r;
} for (int i=1; i<=n; i++)
Z[++tZ]=z1[i],Z[++tZ]=z2[i];
sort(Z+1,Z+tZ+1);Z[0]=Z[1]-1;
for (int i=1; i<=tZ; i++) if (Z[i]!=Z[i-1]) z[++tz]=Z[i]; for (int i=1; i<tz; i++)
{
h=z[i+1]-z[i];
t=ty=tY=0;
to=tmp=0;
for (int j=1; j<=n; j++)
if (z1[j]<=z[i] && z[i+1]<=z2[j])
{
xd[++t].x=x1[j],xd[t].l=y1[j],xd[t].r=y2[j],xd[t].f=0;
xd[++t].x=x2[j],xd[t].l=y1[j],xd[t].r=y2[j],xd[t].f=1;
Y[++tY]=y1[j],Y[++tY]=y2[j];
}
sort(Y+1,Y+tY+1);Y[0]=Y[1]-1;
for (int j=1; j<=tY; j++) if (Y[j]!=Y[j-1]) y[++ty]=Y[j],pp[Y[j]+ff]=++to;
if (!ty) continue;
sort(xd+1,xd+t+1,cmp); build(1,1,ty); for (int j=1; j<t; j++)
{
W=xd[j+1].x-xd[j].x;
L=pp[xd[j].l+ff],R=pp[xd[j].r+ff],F=xd[j].f;
insert(1);
if (xd[j+1].x!=xd[j].x || j+1==t) tmp+=tree[1].sum*W;
}
ans+=h*tmp;
}
printf("%d\n",ans);
return 0;
}

BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞的更多相关文章

  1. 覆盖的面积 HDU - 1255 (线段树-扫描线)模板提

    给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积. Input输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1& ...

  2. BZOJ 4422 Cow Confinement (线段树、DP、扫描线、差分)

    题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=4422 我真服了..这题我能调一天半,最后还是对拍拍出来的...脑子还是有病啊 题解: ...

  3. 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))

    扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...

  4. hdu1255 覆盖的面积 线段树-扫描线

    矩形面积并 线段树-扫描线裸题 #include<stdio.h> #include<string.h> #include<algorithm> #include& ...

  5. BZOJ 1818 线段树+扫描线

    思路: 可以把题目转化成 给你一些沿坐标轴方向的线段 让你求交点个数 然后就线段树+扫描线 搞一搞 (线段不包含断点 最后+n 这种方式 比线段包含断点+各种特判要好写得多) //By SiriusR ...

  6. 【Codeforces720D】Slalom 线段树 + 扫描线 (优化DP)

    D. Slalom time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  7. 【POJ-2482】Stars in your window 线段树 + 扫描线

    Stars in Your Window Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11706   Accepted:  ...

  8. POJ-1151-Atlantis(线段树+扫描线+离散化)[矩形面积并]

    题意:求矩形面积并 分析:使用线段树+扫描线...因为坐标是浮点数的,因此还需要离散化! 把矩形分成两条边,上边和下边,对横轴建树,然后从下到上扫描上去,用col表示该区间有多少个下边,sum代表该区 ...

  9. hdu 1828 线段树扫描线(周长)

    Picture Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Sub ...

随机推荐

  1. 给定一个整数实现奇偶bit位互换

    1.分别取出所有奇数bit位和偶数bit位 0x55555555(对应二进制奇数bit位为1,偶数bit位全为0)&num 0xaaaaaaaa(对应二进制即偶数bit位为1,奇数bit位全为 ...

  2. JavaWeb学习之Servlet(四)----ServletConfig获取配置信息、ServletContext的应用

    [声明] 欢迎转载,但请保留文章原始出处→_→ 文章来源:http://www.cnblogs.com/smyhvae/p/4140877.html [正文] 一.ServletConfig:代表当前 ...

  3. C语言中,&和&&都是做什么的?

    &按位&&逻辑与 逻辑运算符把各个运算的变量(或常量)连接起来组成一个逻辑表达式.逻辑运算符有4个,它们分别是: !(逻辑非). ||(逻辑或).&&(逻辑与) ...

  4. java13-5 JDK1.5以后的一个新特性和Integer的面试题

    1.JDK5的新特性 自动装箱:把基本类型转换为包装类类型 自动拆箱:把包装类类型转换为基本类型 注意一个小问题: 在使用时,Integer x = null;代码就会出现NullPointerExc ...

  5. Android View坐标getLeft, getRight, getTop, getBottom

    1  引起疑惑 分析视图invalidate流程的过程中发现view的left, right, top, bottom跟自己理解的不一样,现在想分析一下这几个值具体的含义. 2  理解坐标,位置概念 ...

  6. smarty插件开发代替注册插件方法registerPlugin

  7. 给 IIS Express 配置虚拟目录

    使用 vs2015 打开旧项目,之前使用 iis 配置站点,然后在 vs 中附加 w3wp.exe 进行开发和调试的. 由于种种原因 iis 上配置站点各种失败. 之后发现,其实在 vs2015 中按 ...

  8. WebApi 消息拦截

    最近公司要求对WebApi 实现服务端信息的监控(服务端信息拦截),由于本人之前没有做过这方便的相关项目所以在做的过程中也是困难重重,探索的过程也是非常痛苦的,好歹最终也算实现了这个功能.所以将这个分 ...

  9. sqlalchemy 的 Core 方式使用示例

    知乎: sqlalchemy 的 Core 方式操作数据是一种怎样的体验? 答: 爽! 本文基于:win 10 + python 3.4 + sqlalchemy 1.0.13 基本步骤如下: 1. ...

  10. LeetCode 笔记26 Single Number II

    Given an array of integers, every element appears three times except for one. Find that single one. ...