线段树 扫描线 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个矩形,每个矩形给了左下角和右上角的坐标,矩形可能会重叠,求的是矩形最后的面积. 题解思路 这个是我线段树扫描线的第一题,听了学长的讲解 ...
随机推荐
- 几行代码实现cookie的盗取
前言 上一篇文章中介绍了XSS(跨站脚本攻击)简单原理与几种类型.接下来通过实例用几行代码实现cookie的盗取. 正文 这里测试用的工具是DVWA(可以本地搭建,前面文章有介绍),和phpstudy ...
- Java成长第四集--文本处理IO流
Java IO流在实际业务中使用的频率还是蛮高的,一些业务场景比如,文件的上传和导出,文件的读取等基本都是通过操作IO流来实现的,所以IO流是我们现在学习过程中必须要掌握的技能之一,熟练的使用IO流, ...
- AJ学IOS 之微博项目实战(12)发送微博自定义工具条代理实现点击事件
AJ分享,必须精品 一:效果 二:封装好的工具条 NYComposeToolbar.h 带代理方法 #import <UIKit/UIKit.h> typedef enum { NYCom ...
- AJ学IOS(03)UI之纯代码实现UI——图片查看器
AJ分享,必须精品 先看效果 主要实现类似看新闻的一个界面,不用拖拽,纯代码手工写. 首先分析app可以很容易知道他这里有两个UILabel一个UIImageView还有两个UIButton 定义UI ...
- 实验一 熟悉IDLE和在线编程平台
实验目的 1.掌握python IDLE集成开发环境的安装与使用 2.熟悉在线编程平台 3.掌握基本的python程序编写.编译与运行程序的方法 实验内容 1.按照实验指导安装IDLE,尝试交互式运行 ...
- G. 平行线
单点时限: 2.0 sec 内存限制: 512 MB “大猩猩为什么不喜欢平行线?”“因为平行线没有相交”哈哈哈哈哈哈哈哈哈 为了管理动物园不听话的大猩猩们,动物管理员Boctorio 决定去远方的A ...
- UML(续)
活动图 活动图定义 活动图描述了在一个过程中,顺序的/并行的活动及其之间的关系 应用于商业过程.工作流(业务过程).复杂算法的建模 活动图是顶点和弧的集合 活动节点 动作 流 对象值 注解和约束等 建 ...
- 跑Linux内存占用率的shell脚本
#!/bin/bash ################################################################ # Mem Used Script # eg. ...
- [PHP] 文件创建、写入、读取
创建$p = fopen('text.txt','a+b'); 写入第一种方式//var_export方式存储数组到文件中 //这中方式存浮点型数据,存储后会多很多数字!只适合简单的存储吧!我感觉! ...
- Django文档阅读-Day3
Django文档阅读-Day3 Writing your first Django app, part 3 Overview A view is a "type" of Web p ...