题目链接:http://poj.org/problem?id=1177

题目大意:若干个矩形,求这些矩形重叠形成的图形的轮廓周长。

解题思路:这里引用一下大牛的思路:kuangbin

总体思路:

1.沿X轴离散化建树

2.按Y值从小到大排序平行与X轴的边,然后顺序处理

如果遇到矩形下面那条边则插入到线段树中,遇到矩形上面的边则将相应的边删除掉

根据线段树当前的状态统计长度

第二点是本题的核心思想,偶再举个例:

第一次求出的部分很好理解.

第二次求出的为什么会少了中间那部分.那是因为插入的新线段覆盖了第一条,此时线段树返回的长度是新的那一条的长度,将这个值再减去上次的就少了中间那部分

第三次因为是矩形的上边,所以要删除在那条长的线段.此时的线段树返回的则是第一次的长度,将此值减去第二次返回值,再取其负值就是红色X轴那部分了

最后那条X轴的,再补上就行了。

我写的稍微有点不同,不过大概也就是这个思路了。总结一下就是矩形下位边cnt+1,上位边cnt-1,求tree[1].sum,这些步骤跟求矩形面积并是一样的。

然后按照扫描线从小到大一次跟新,ans+=abs(上一次的测度-更新后的测度)。

然后就按x,y方向扫描线各求一遍,加在一起就是总的周长。(好像还是有点问题,就是重边会出错,不会改啊!!!算了,等以后变强了再来改0 0)

这题我没有离散化,因为数据不是很大也没有小数所以就懒得写了。。。

代码:

 #include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<string>
#define LC(a) (a<<1)
#define RC(a) (a<<1|1)
#define MID(a,b) ((a+b)>>1)
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const int N=1e4+; struct Node{
int l,r,cnt,sum;//sum为测度
}tree[N**]; struct node{
int l,r,h,flag;
node(){}
node(double a,double b,double c,double d){
l=a;r=b;h=c;flag=d;
}
}a[N],b[N]; bool cmp(node a,node b){
return a.h<b.h;
}
//因为每条线段对应删除的线段是严格出现的,不需要Lazy也就不需要pushdown()
void pushup(int p) {
if(tree[p].cnt>)
tree[p].sum=tree[p].r-tree[p].l+;
else if(tree[p].l==tree[p].r)
tree[p].sum=;
else
tree[p].sum=tree[LC(p)].sum+tree[RC(p)].sum;
} void build(int p,int l,int r){
tree[p].l=l;
tree[p].r=r;
if(l==r){
tree[p].cnt=tree[p].sum=;
return;
}
build(LC(p),l,MID(l,r));
build(RC(p),MID(l,r)+,r);
pushup(p);
} void update(int p,int l,int r,int cnt){
if(l>tree[p].r||r<tree[p].l)
return;
if(l<=tree[p].l&&r>=tree[p].r&&tree[p].cnt!=-){
tree[p].cnt+=cnt;
pushup(p);
return;
}
update(LC(p),l,r,cnt);
update(RC(p),l,r,cnt);
pushup(p);
} int main(){
int n;
while(~scanf("%d",&n)){
int m1=,m2=;
for(int i=;i<=n;i++){
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1+=N,x2+=N,y1+=N,y2+=N;//防止x,y出现负数
a[++m1]=node(x1,x2,y1,);
b[m1]=node(y1,y2,x1,);
a[++m1]=node(x1,x2,y2,-);
b[m1]=node(y1,y2,x2,-);
}
sort(a+,a++m1,cmp);
sort(b+,b++m1,cmp);
//自下往上扫描一遍
build(,,*N-);
int ans=;
for(int i=;i<=m1;i++){
int last=tree[].sum;
int l=a[i].l;
int r=a[i].r-;
update(,l,r,a[i].flag);
ans+=abs(tree[].sum-last);
}
//自左往右扫描一遍
build(,,*N-);
for(int i=;i<=m1;i++){
int last=tree[].sum;
int l=b[i].l;
int r=b[i].r-;
update(,l,r,b[i].flag);
ans+=abs(tree[].sum-last);
}
printf("%d\n",ans);
}
return ;
}

最新文章

  1. linux下配置matlab运行环境(MCR)
  2. [Oracle] Bulk Insert Data
  3. mysql 的 find_in_set函数使用方法
  4. 【C语言】04-函数
  5. [转]Web Service Authentication
  6. java 多线程——quartz 定时调度的例子
  7. jsp java 数据库 乱码总结
  8. C++中的const关键字
  9. fzu1759:数论高次幂降幂
  10. 跨服务器的sql使用
  11. [转]php 在各种web服务器的运行模式
  12. java8 泛型声明 The diamond operator (&quot;&lt;&gt;&quot;) should be used
  13. while循环_do_while循环_switch
  14. linux安装ssh服务
  15. 英语口语练习系列-C33-露营-谈论日期-离思
  16. JDBC driver for MySQL连接提示&quot;The connection property &#39;zeroDateTimeBehavior&#39; acceptable values are: &#39;CONVERT_TO_NULL&#39;, &#39;EXCEPTION&#39; or &#39;ROUND&#39;. The value &#39;convertToNull&#39; is not acceptable.&quot;解决方案
  17. CPP--借助神器VS理解内存存储(含大小端对齐)
  18. 从实践出发:微服务布道师告诉你Spring Cloud与Spring Boot他如何选择
  19. idea导入eclipse中的maven项目
  20. react初始化阶段

热门文章

  1. [Leetcode] combination sum ii 组合之和
  2. SRM16 B-2(DP)
  3. pexpect正确的打开方式
  4. [10.18模拟赛] 序列 (DP)
  5. 手脱ASProtect v1.23 RC1(无Stolen Code)
  6. 团队题目需求分析-NABCD
  7. [LeetCode] 17. Letter Combinations of a Phone Number ☆☆
  8. Maven命令创建java项目
  9. Xamarin入门浅析
  10. Linux 命令行生成密码的 10 种方式