线段树 扫描线 L - Atlantis HDU - 1542 M - City Horizon POJ - 3277 N - Paint the Wall HDU - 1543
我觉得要注意的几点
1 我的模板线段树的叶子节点存的都是 x[L]~x[L+1]
2 如果没有必要这个lazy 标志是可以不下传的 也就省了一个push_down
3 注意push_up 写法有点不一样,不过是可以改成一样的。
简单裸题*2
L - Atlantis HDU - 1542
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = ;
double v[maxn];
struct node {
double l, r, h;
int d;
node(double l = , double r = , double h = , int d = ) :l(l), r(r), h(h), d(d) {}
}line[maxn];
bool cmp(node a, node b) {
return a.h < b.h;
}
double sum[maxn * ];
int lazy[maxn * ];
void build(int id, int l, int r) {
sum[id] = ;
lazy[id] = ;
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
} void push_up(int id, int l, int r) {
if (lazy[id]) sum[id] = v[r + ] - v[l];
else sum[id] = sum[id << ] + sum[id << | ];
} void update(int id, int l, int r, int x, int y, int d) {
if (x <= l && y >= r) {
lazy[id] += d;
push_up(id, l, r);
return;
}
int mid = (l + r) >> ;
if (x <= mid) update(id << , l, mid, x, y, d);
if (y > mid) update(id << | , mid + , r, x, y, d);
push_up(id, l, r);
} int main() {
int n, cas = ;
while (scanf("%d", &n) != EOF && n) {
int cnt = , tot = ;
for (int i = ; i <= n; i++) {
double x1, y1, x2, y2;
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
v[++cnt] = x1, v[++cnt] = x2;
line[++tot] = node(x1, x2, y1, ), line[++tot] = node(x1, x2, y2, -);
}
sort(v + , v + + cnt);
sort(line + , line + + tot, cmp);
int len = unique(v + , v + + cnt) - v - ;
double ans = ;
build(, , len - );
for (int i = ; i < tot; i++)//这里注意只需要要tot-1即可,因为我们每次都是按底算的
{
int l = lower_bound(v + , v + + len, line[i].l) - v;
int r = lower_bound(v + , v + + len, line[i].r) - v - ;
update(, , len - , l, r, line[i].d);
ans += sum[] * (line[i + ].h - line[i].h);
}
printf("Test case #%d\n", ++cas);
printf("Total explored area: %.2lf\n\n", ans);
}
return ;
}
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn = 8e4 + ;
ll v[maxn];
struct node {
ll l, r, h;
int d;
node(ll l = , ll r = , ll h = , int d = ) :l(l), r(r), h(h), d(d) {}
}line[maxn];
bool cmp(node a, node b) {
return a.h < b.h;
}
ll sum[maxn * ];
int lazy[maxn * ];
void build(int id, int l, int r) {
sum[id] = ;
lazy[id] = ;
if (l == r) return;
int mid = (l + r) >> ;
build(id << , l, mid);
build(id << | , mid + , r);
} void push_up(int id, int l, int r) {
if (lazy[id]) sum[id] = v[r + ] - v[l];
else sum[id] = sum[id << ] + sum[id << | ];
} void update(int id, int l, int r, int x, int y, int d) {
if (y<l || x>r) return;
// printf("id=%d l=%d r=%d x=%d y=%d\n", id, l, r, x, y);
if (x <= l && y >= r) {
lazy[id] += d;
if (lazy[id]) sum[id] = v[r + ] - v[l];
else sum[id] = sum[id << ] + sum[id << | ];
return;
}
int mid = (l + r) >> ;
if (x <= mid) update(id << , l, mid, x, y, d);
if (y > mid) update(id << | , mid + , r, x, y, d);
push_up(id, l, r);
} int main() {
int n, cnt = , tot = ;
scanf("%d", &n);
for (int i = ; i <= n; i++) {
ll l, r, h;
scanf("%lld%lld%lld", &l, &r, &h);
v[++cnt] = l, v[++cnt] = r;
line[++tot] = node(l, r, , ), line[++tot] = node(l, r, h, -);
}
sort(v + , v + + cnt);
sort(line + , line + + tot, cmp);
int len = unique(v + , v + + cnt) - v - ;
build(, , len - );
ll ans = ;
for (int i = ; i < tot; i++) {
int l = lower_bound(v + , v + + len, line[i].l) - v;
int r = lower_bound(v + , v + + len, line[i].r) - v - ;
// printf("l=%d r=%d\n", l, r);
update(, , len - , l, r, line[i].d);
ans += sum[] * (line[i + ].h - line[i].h);
// printf("%lld %lld ans=%lld %lld sum=%lld\n", line[i].l, line[i].r, ans, line[i].h, sum[1]);
// printf("%lld %lld ans=%lld %lld\n", line[i + 1].l, line[i + 1].r, ans, line[i + 1].h);
// printf("\n\n");
}
printf("%lld\n", ans);
return ;
}
然后每次对于这个矩形的每一个y轴的这一段都查一下,然后如果已经被覆盖了,就删去这一段,然后更新这一段。
这个题目其实还是很好写的,但是要注意push_down的写法。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <cstring>
using namespace std;
const int maxn = ;
struct rect
{
int x1, y1, x2, y2, col;
rect(int x1=,int y1=,int x2=,int y2=,int col=):x1(x1),y1(y1),x2(x2),y2(y2),col(col){}
}ex[maxn]; int vx[maxn * ], vy[maxn * ], color[maxn];
int sum[maxn][maxn * ], lazy[maxn][maxn * ]; void build(int i,int id,int l,int r)
{
sum[i][id] = lazy[i][id] = ;
if (l == r) return;
int mid = (l + r) >> ;
build( i,id << , l, mid);
build(i, id << | , mid + , r);
} void push_up(int i,int id)
{
sum[i][id] = sum[i][id << ] + sum[i][id << | ];
// printf("sum[%d][%d]=%d\n", i, id, sum[i][id]);
} void push_down(int i,int id,int l,int r)
{
if (lazy[i][id] == ) return;
int mid = (l + r) >> ;
sum[i][id << ] = vx[mid + ] - vx[l];
sum[i][id << | ] = vx[r + ] - vx[mid + ];
lazy[i][id << ] = lazy[i][id << | ] = lazy[i][id];
// printf("l=%d r=%d mid=%d\n", l, r, mid);
// printf("x sum[%d][%d]=%d\n", i, id<<1, sum[i][id<<1]);
// printf("x sum[%d][%d]=%d\n", i, id<<1|1, sum[i][id<<1|1]);
lazy[i][id] = ;
} void update(int i,int id,int l,int r,int x,int y)
{
if (x <= l && y >= r) {
sum[i][id] = vx[r + ] - vx[l];
// printf("l=%d r=%d\n", l, r);
// printf("ww sum[%d][%d]=%d\n", i, id, sum[i][id]);
lazy[i][id] = ;
return;
}
int mid = (l + r) >> ;
push_down(i, id, l, r);
if (x <= mid) update(i, id << , l, mid, x, y);
if (y > mid) update(i, id << | , mid + , r, x, y);
push_up(i, id);
} int query(int i,int id,int l,int r,int x,int y)
{
if (x <= l && y >= r) return sum[i][id];
int mid = (l + r) >> , ans = ;
push_down(i, id, l, r);
if (x <= mid) ans += query(i, id << , l, mid, x, y);
if (y > mid) ans += query(i, id << | , mid + , r, x, y);
return ans;
} int main()
{
int w, h, n, cas = ;
while (scanf("%d%d", &w, &h) && (w + h)) {
memset(color, , sizeof(color));
int tot = , cnt = ;
scanf("%d", &n);
vx[++tot] = , vx[++tot] = w;
vy[++cnt] = , vy[++cnt] = h;
for (int i = ; i <= n; i++) {
int x1, y1, x2, y2, col;
scanf("%d%d%d%d%d", &x1, &y1, &x2, &y2, &col);
ex[i] = rect(x1, y1, x2, y2, col);
vx[++tot] = x1, vx[++tot] = x2;
vy[++cnt] = y1, vy[++cnt] = y2;
}
sort(vx + , vx + + tot);
sort(vy + , vy + + cnt);
int lenx = unique(vx + , vx + + tot) - vx - ;
int leny = unique(vy + , vy + + cnt) - vy - ;
// for (int i = 1; i <= lenx; i++) printf("vx[%d]=%d\n", i, vx[i]);
for (int i = ; i < leny; i++) build(i, , , lenx - );
for (int i = n; i >= ; i--) {
// printf("i=%d\n", i);
int col = ex[i].col;
int ans = (ex[i].x2 - ex[i].x1)*(ex[i].y2 - ex[i].y1);
int lx = lower_bound(vx + , vx + + lenx, ex[i].x1) - vx;
int ly = lower_bound(vy + , vy + + leny, ex[i].y1) - vy;
int rx = lower_bound(vx + , vx + + lenx, ex[i].x2) - vx - ;
int ry = lower_bound(vy + , vy + + leny, ex[i].y2) - vy - ;
for (int j = ly; j <= ry; j++) {
int res = query(j, , , lenx - , lx, rx);
ans -= (vy[j + ] - vy[j])*res;
// printf("j=%d\n", j);
// printf("lx=%d ly=%d rx=%d ry=%d\n", lx, ly, rx, ry);
// printf("x1=%d y1=%d x2=%d y2=%d\n", ex[i].x1, ex[i].y1, ex[i].x2, ex[i].y2);
// printf("res=%d %d ans=%d\n", res, vy[j + 1] - vy[j],ans);
update(j, , , lenx - , lx, rx);
}
color[col] += ans;
// printf("color[%d]=%d\n", col, color[col]);
// printf("\n");
}
int num = ;
if (cas) printf("\n");
printf("Case %d:\n", ++cas);
for (int i = ; i <= ; i++) {
if (color[i]) {
printf("%d %d\n", i, color[i]);
num++;
}
}
if (num == ) printf("There is %d color left on the wall.\n", num);
else printf("There are %d colors left on the wall.\n", num);
}
return ;
}
/*
10 8
4
1 9 5 10 9
1 8 2 9 8
7 1 10 8 4
6 2 9 6 4
0 0 */
线段树 扫描线 L - Atlantis HDU - 1542 M - City Horizon POJ - 3277 N - Paint the Wall HDU - 1543的更多相关文章
- HDU 1542 - Atlantis - [线段树+扫描线]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1542 Time Limit: 2000/1000 MS (Java/Others) Memory Li ...
- 线段树扫描线(一、Atlantis HDU - 1542(覆盖面积) 二、覆盖的面积 HDU - 1255(重叠两次的面积))
扫描线求周长: hdu1828 Picture(线段树+扫描线+矩形周长) 参考链接:https://blog.csdn.net/konghhhhh/java/article/details/7823 ...
- hdu1542 Atlantis (线段树+扫描线+离散化)
Atlantis Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total S ...
- HDU 1828“Picture”(线段树+扫描线求矩形周长并)
传送门 •参考资料 [1]:算法总结:[线段树+扫描线]&矩形覆盖求面积/周长问题(HDU 1542/HDU 1828) •题意 给你 n 个矩形,求矩形并的周长: •题解1(两次扫描线) 周 ...
- hdu 4052 线段树扫描线、奇特处理
Adding New Machine Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Othe ...
- hdu 1828 线段树扫描线(周长)
Picture Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- hdu1542 Atlantis 线段树--扫描线求面积并
There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some ...
- HDU 1264 Counting Squares (线段树-扫描线-矩形面积并)
版权声明:欢迎关注我的博客.本文为博主[炒饭君]原创文章,未经博主同意不得转载 https://blog.csdn.net/a1061747415/article/details/25471349 P ...
- Atlantis poj1151 线段树扫描线
Atlantis poj1151 线段树扫描线 题意 题目给了n个矩形,每个矩形给了左下角和右上角的坐标,矩形可能会重叠,求的是矩形最后的面积. 题解思路 这个是我线段树扫描线的第一题,听了学长的讲解 ...
随机推荐
- Linux的文本编辑和文本内容查看命令
Linux的文本编辑和文本内容查看命令 1.文本编辑命令 vi:用于编辑文本文件,基本上可以分为三种模式,分别是一般模式.编辑模式.命令行模式. 一般模式:当编辑一个文件时,刚进入文件就是一般模 ...
- 数据结构和算法(Golang实现)(20)排序算法-选择排序
选择排序 选择排序,一般我们指的是简单选择排序,也可以叫直接选择排序,它不像冒泡排序一样相邻地交换元素,而是通过选择最小的元素,每轮迭代只需交换一次.虽然交换次数比冒泡少很多,但效率和冒泡排序一样的糟 ...
- DPK
一.概念 dpk文件是Delphi的包文件,有dpk文件的组件安装比较方便.一般来说,支持不同版本Delphi的组件会有不同的dpk文件,一般以7结尾的dpk文件是支持Delphi 7的.如果没有支持 ...
- python高级特性之封包与解包
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:kwsy PS:如有需要Python学习资料的小伙伴可以加点击下方链接 ...
- python干货-类属性和方法,类的方法重写
类属性与方法 类的私有属性 __private_attrs: 两个下划线开头,表明为私有,外部不可用,内部使用时self.__private_attrs. 类的方法 在类的内部,使用 def 关键字来 ...
- Websocket直播间聊天室教程 - GoEasy快速实现聊天室
最近两年直播那个火啊,真的是无法形容!经常有朋友问起,我想实现一个直播间聊天或者我想开发一个聊天室, 要如何开始呢? 今天小编就手把手的教你用GoEasy做一个聊天室,当然也可以用于直播间内的互动.全 ...
- POJ 跳蚤
Z城市居住着很多只跳蚤.在Z城市周六生活频道有一个娱乐节目.一只跳蚤将被请上一个高空钢丝的正中央.钢丝很长,可以看作是无限长.节目主持人会给该跳蚤发一张卡片.卡片上写有N+1个自然数.其中最后一个是M ...
- python圆周率计算小程序(非常慢)
源码: from math import fabs #导入数学模块 from time import perf_counter #导入时间模块 from numba import jit @jit d ...
- Matlab学习-(4)
1. 函数 1.1 原始方法 之前我调用函数的方法是,首先写好函数文件,然后保存,然后在主函数中调用.这种方法的不足在于会导致你的工作目录的文件太多,从而导致很乱.在网上找了一些解决方法. 1.2 本 ...
- PHP函数:php_sapi_name
php_sapi_name() - 返回 web 服务器和 PHP 之间的接口类型. SAPI(Server Application Programming Interface)服务器应用程序编程接 ...