poj1177Picture(线段树-周长并)
神奇的扫描线啊
估计之前刷面积并的时候太急了 没来得及理解 。。
有一大段代码是与面积并一模一样的 都是离散化 更新
面积并是扫描的x 这次也一样
因为周长只算外围的 所以扫描到一条x边时 要减去上一次扫描到的 对于Y方向上 就是与面积并不大一样的地方了
看篇带图的讲解吧 网上的题解都大同小异 估计出自一人之手
http://blog.sina.com.cn/s/blog_691ce2b7010177dz.html
它是扫描的Y 其实方法是一样的 横过来就是
对于我的代码 自己感觉不好理解在于求区间数
#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stdlib.h>
using namespace std;
#define N 10010
#define LL long long
struct node
{
int lx,rx,y,d;
node(){}
node(int a,int b,int c,int d):lx(a),rx(b),y(c),d(d){}
bool operator < (const node &S) const
{
if(y == S.y) return d > S.d;
return y<S.y;
}
}mat[N];
int que[N],sum[N<<],lg[N<<],rg[N<<],seg[N<<];
int cnt[N<<];
LL ans=;
int bin(int k,int low,int high)
{
int m;
while(low<=high)
{
m = (low+high)/;
if(que[m]==k)
return m;
if(que[m]>k)
high = m-;
else
low = m+;
}
return m;
}
void up(int l,int r,int w)
{
if(cnt[w])//入边就更新这段的值 及区间数 (1个区间 2条Y边)
{
sum[w] = que[r+]-que[l];
seg[w] = ;
lg[w] = ;
rg[w] = ;
}
else if(l==r)
{
sum[w] = seg[w] = lg[w] = rg[w] = ;//出边的话 消除这条边
}
else//非出入边 向上更新 与平常线段树一样 等于子孩子相加
{
sum[w] = sum[w<<]+sum[w<<|];
seg[w] = seg[w<<]+seg[w<<|];
lg[w] = lg[w<<];
rg[w] = rg[w<<|];
if(lg[w<<|]&&rg[w<<])//左右相连 减去重复的
seg[w]-=;
}
}
void update(int a,int b,int d,int l,int r,int w)
{
if(a<=l&&b>=r)
{
cnt[w]+=d;
up(l,r,w);
return ;
}
int m = (l+r)>>;
if(a<=m)
update(a,b,d,l,m,w<<);
if(b>m)
update(a,b,d,m+,r,w<<|);
up(l,r,w);
}
int main()
{
int i,n,a,b,c,d;
while(scanf("%d",&n)!=EOF)
{
int num=;
for(i = ; i <= n ; i++)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
que[num] = a;
mat[num++] = node(a,c,b,);
que[num] = c;
mat[num++] = node(a,c,d,-);
}
sort(que,que+num);
sort(mat,mat+num);
int k = ;
for(i = ; i < num ; i++)
{
if(que[i]!=que[i-])
que[k++] = que[i];
}
memset(cnt,,sizeof(cnt));
memset(sum,,sizeof(sum));
memset(lg,,sizeof(lg));
memset(rg,,sizeof(rg));
memset(seg,,sizeof(seg));
int o=;
ans=;
mat[num].y = ;
for(i = ; i < num ; i++)
{
int l = bin(mat[i].lx,,k-);
int r = bin(mat[i].rx,,k-)-;
update(l,r,mat[i].d,,k-,);
ans+=seg[]*(mat[i+].y-mat[i].y);
ans+=abs(sum[]-o);
o = sum[];
}
printf("%lld\n",ans);
}
return ;
}
poj1177Picture(线段树-周长并)的更多相关文章
- poj 1177 Picture(线段树周长并)
题目链接:http://poj.org/problem?id=1177 题意:给你n个矩形问你重叠后外边缘总共多长. 周长并与面积并很像只不过是处理的时候是 增加的周长=abs(上一次的线段的长度 ...
- POJ 1177 Picture(线段树周长并)
描述 A number of rectangular posters, photographs and other pictures of the same shape are pasted on ...
- HDU 1828 / POJ 1177 Picture --线段树求矩形周长并
题意:给n个矩形,求矩形周长并 解法:跟求矩形面积并差不多,不过线段树节点记录的为: len: 此区间线段长度 cover: 此区间是否被整个覆盖 lmark,rmark: 此区间左右端点是否被覆盖 ...
- HDU 1828 / POJ 1177 Picture (线段树扫描线,求矩阵并的周长,经典题)
做这道题之前,建议先做POJ 1151 Atlantis,经典的扫描线求矩阵的面积并 参考连接: http://www.cnblogs.com/scau20110726/archive/2013/0 ...
- hdu 1828 线段树扫描线(周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- hdu 1828 Picture(线段树扫描线矩形周长并)
线段树扫描线矩形周长并 #include <iostream> #include <cstdio> #include <algorithm> #include &l ...
- 51nod 1206 Picture 矩形周长求并 | 线段树 扫描线
51nod 1206 Picture 矩形周长求并 | 线段树 扫描线 #include <cstdio> #include <cmath> #include <cstr ...
- POJ 1177 Picture(线段树:扫描线求轮廓周长)
题目链接:http://poj.org/problem?id=1177 题目大意:若干个矩形,求这些矩形重叠形成的图形的轮廓周长. 解题思路:这里引用一下大牛的思路:kuangbin 总体思路: 1. ...
- luogu P1856 [USACO5.5]矩形周长Picture 扫描线 + 线段树
Code: #include<bits/stdc++.h> #define maxn 200007 #define inf 100005 using namespace std; void ...
随机推荐
- Linq 中的TakeWhile 和 SkipWhile
这两个概念容易搞混 理解了一番后 在这里写下便于记忆 SkipWhile 可以理解为如果条件满足 就一直跳过 知道不满足后 就取剩下的所有元素(后面的不会再判断) TakeWhile 可以理解为 ...
- SQL Constraint/Index
1.SQL Constraint Integrity Constraints are used to apply business rules for the database tables. The ...
- Installation Phases and In-Script Execution for Custom Actions in Windows Installer
用 InstallShield 依照 Custom Action Wizard 创建 Custom Action 时,会遇到下面的几个选项: In-Script Execution Install U ...
- Android_时间服务
接着上一节,这次我查看了Android的时间服务,觉得帮助很大,解决了我很多疑问,下面我就自己总结了一下,加深了自己的印象,好记性不如烂笔头,还真讲得很不错,收下吧?看下图如何利用线程更新UI组件 重 ...
- echshop 微信扫码支付 遇到的问题
参考的网站 (转)http://www.ecshop119.com/ecshopjc-937.html(转)http://www.6gdown.com/softedupage/58929.html ...
- Make和Makefile
无论是在Linux还是在Unix环境中,make都是一个非常重要的编译命令.不管是自己进行项目开发还是安装应用软件,我们都经常要用到make或make install.利用make工具,我们可以将大型 ...
- JS判断是否微信浏览器
JS判断是否微信浏览器 function isWeixinBrowser(){ var ua = navigator.userAgent.toLowerCase(); return (/microme ...
- Python多线程启动http.server
OS: Windows 8.1 with update 关键字:Python3.4, http.server, Thread 例子代码如下: import os from threading impo ...
- python学习_应用pickle模块封装和拆封数据对象
学习文件数据处理的时候了解到有pickle模块,查找官方文档学习了一些需要用到的pickle内容. 封装是一个将Python数据对象转化为字节流的过程,拆封是封装的逆操作,将字节文件或字节对象中的字节 ...
- hdu 2222 Keywords Search ac自动机入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2222 题意:有N(N <= 10000)个长度不超过50的模式串和一个长度不超过1e6的文本串. ...