51nod 1206 Picture 矩形周长求并 | 线段树 扫描线


#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
#define INF 0x3f3f3f3f
#define space putchar(' ')
#define enter putchar('\n')
template <class T>
bool read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
else if(c == EOF) return 0;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op) x = -x;
return 1;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 100005;
struct Query {
int l, r, h, x;
bool operator < (const Query &b) const{
return h == b.h ? x > b.x : h < b.h;
/*
对于高度相同的修改操作,要让入边在前面,为的是应对这种数据:
2
0 0 1 1
0 1 1 2
*/
}
} Q[2 * N];
int n, lst[2 * N], tot, cnt[8 * N], len[8 * N], sum[8 * N], lsum[8 * N], rsum[8 * N];
ll ans;
/*
变量解释:
lst、tot: 用于离散化
cnt: 记录线段树上一个节点是否已被覆盖
len: 记录线段树上一个节点所代表的区间被覆盖了多长
sum: 记录线段树上一个节点所代表的区间有多少条竖线
lsum、rsum: 分别记录一个区间左右、端点是否有竖线,因为用儿子更新某父亲节点竖线数时,如果左儿子的右端点和右儿子的左端点都有竖线,那么这两条竖线其实是一条竖线。
*/
void pushup(int k, int l, int r){
if(cnt[k]) {
len[k] = lst[r + 1] - lst[l];
lsum[k] = rsum[k] = 1;
sum[k] = 2;
}
else if(l == r) sum[k] = len[k] = lsum[k] = rsum[k] = 0;
else{
len[k] = len[k << 1] + len[k << 1 | 1];
lsum[k] = lsum[k << 1], rsum[k] = rsum[k << 1 | 1];
sum[k] = sum[k << 1] + sum[k << 1 | 1];
if(rsum[k << 1] && lsum[k << 1 | 1]) sum[k] -= 2;
}
}
void change(int k, int l, int r, int ql, int qr, int x){
if(ql <= l && qr >= r){
cnt[k] += x;
pushup(k, l, r);
return;
}
int mid = (l + r) >> 1;
if(ql <= mid) change(k << 1, l, mid, ql, qr, x);
if(qr > mid) change(k << 1 | 1, mid + 1, r, ql, qr, x);
pushup(k, l, r);
}
int getx(int x){
return lower_bound(lst + 1, lst + tot + 1, x) - lst;
//写给自己:注意离散化不要又双叒叕把数组范围打错!不要打成2*n!
}
int main(){
read(n);
for(int i = 1, xa, ya, xb, yb; i <= n; i++){
read(xa), read(ya), read(xb), read(yb);
lst[2 * i - 1] = xa, lst[2 * i] = xb;
Q[2 * i - 1] = (Query){xa, xb, ya, 1};
Q[2 * i] = (Query){xa, xb, yb, -1}; //进行愉快的离散化
}
sort(Q + 1, Q + 2 * n + 1);
sort(lst + 1, lst + 2 * n + 1);
tot = unique(lst + 1, lst + 2 * n + 1) - lst - 1;
for(int i = 1, lastlen = 0; i <= 2 * n; i++){
if(i != 1) ans += (ll) sum[1] * (Q[i].h - Q[i - 1].h);
change(1, 1, tot, getx(Q[i].l), getx(Q[i].r) - 1, Q[i].x);
ans += (ll) abs(lastlen - len[1]), lastlen = len[1];
}
write(ans), enter;
return 0;
}

51nod 1206 Picture 矩形周长求并 | 线段树 扫描线的更多相关文章

  1. POJ 1151 Atlantis 矩形面积求交/线段树扫描线

    Atlantis 题目连接 http://poj.org/problem?id=1151 Description here are several ancient Greek texts that c ...

  2. 51NOD 1962 区间计数 单调栈+二分 / 线段树+扫描线

     区间计数   基准时间限制:1.5 秒 空间限制:262144 KB 分值: 80   两个数列 {An} , {Bn} ,请求出Ans, Ans定义如下: Ans:=Σni=1Σnj=i[max{ ...

  3. HDU 1828“Picture”(线段树+扫描线求矩形周长并)

    传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...

  4. hdu1828 Picture(线段树+扫描线+矩形周长)

    看这篇博客前可以看一下扫描线求面积:线段树扫描线(一.Atlantis HDU - 1542(覆盖面积) 二.覆盖的面积 HDU - 1255(重叠两次的面积))  解法一·:两次扫描线 如图我们可以 ...

  5. hdu 1828 Picture(线段树扫描线矩形周长并)

    线段树扫描线矩形周长并 #include <iostream> #include <cstdio> #include <algorithm> #include &l ...

  6. [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)

    [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...

  7. hdu1542 线段树扫描线求矩形面积的并

    题意:       给你n个正方形,求出他们的所占面积有多大,重叠的部分只能算一次. 思路:       自己的第一道线段树扫描线题目,至于扫描线,最近会写一个总结,现在就不直接在这里写了,说下我的方 ...

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

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

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

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

随机推荐

  1. 树莓派操控SG90舵机

    目录 舵机接线 PWM介绍 使用PWM控制舵机 这里使用树莓派来操作sg90的舵机.先看一下这个舵机的样子: 这就是传说中的SG90舵机啦,转角是0-180. SG90舵机接线: SG90舵机有三条线 ...

  2. docker 一篇文章学习容器化

      什么是镜像?什么是容器?   一句话回答:镜像是类,容器是实例   docker 基本操作命令:   删除所有container: docker rm $(docker ps -a -q)   删 ...

  3. DP使用GUI推送WIN客户端是报110:1022错误的解决办法

    在使用GUI推送WIN客户端时,输入用户名和密码后报错: [Critical 110::1022]  Cannot connect to the SCM (Service Control Manage ...

  4. git 创建管理多用户

    <搬运> Windows下Git多账号配置,同一电脑多个ssh-key的管理 一台电脑上的git同时使用两个github账户 git之https或http方式设置记住用户名和密码的方法

  5. rest_framework_api规范

    目录 一.什么是RESTful 二.什么是API 三.RESTful API规范 四.基于Django实现API 五.基于Django Rest Framework框架实现 一. 什么是RESTful ...

  6. 对视频播放软件KMplayer的评价

    刚进入大一的时候接触到了KMplayer,由于当时收集了不同格式的电影视频却没有合适的播放器播放出来,后来在网上知道了所谓的万能播放器的KMplayer,下载用了过后,才知道这的确是一款万能播放器. ...

  7. Notes of Daily Scrum Meeting(11.4)

    Notes of Daily Scrum Meeting 2014年11月4日  星期二  20:30—21:00 团队成员 今日团队任务 当日工作分配额 完成情况 陈少杰 阅读理解代码中底层与数据库 ...

  8. Sprint11

    进展:基本设置和显示已经完成,然后是可以通过长按事件弹出对话框可以进行停用.修改.取消该事件提醒的实现,通过触发动作跳转到各个部分页面.

  9. BETA随笔6/7

    前言 我们居然又冲刺了·六 团队代码管理github 站立会议 队名:PMS 530雨勤(组长) 过去两天完成了哪些任务 新方案代码比之前的更简单,但是对场景的要求相应变高了,已经实现,误差感人 代码 ...

  10. 在onResume()中调用getIntent()得不到Extra的问题

    之前 想做activity间的传值,注意 不是 startActivityforResult的那种, 在启动了多层activity再次启动activity想进入到singleTask的MainActi ...