线段树 扫描线 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个矩形,每个矩形给了左下角和右上角的坐标,矩形可能会重叠,求的是矩形最后的面积. 题解思路 这个是我线段树扫描线的第一题,听了学长的讲解 ...
随机推荐
- Win10 cmd的ssh命令连接linux虚拟机
其实就是一个小发现了~ 闲的没事的时候在cmd里面敲了ssh命令,居然提示是一个命令,貌似以前是没有这功能的.然后就打开虚拟机试试能不能远程连接.没想到还成功了~ 有了这功能就省得安装专门的远程连接工 ...
- Floyd-例题-实现-我的第一篇博客
https://www.cnblogs.com/lbssxz/p/11014911.html 这是网上看到的题目,以上是原博主的解答和题目来源(没找到别的题目来源) 题目大意: 城市交通费 [问题描述 ...
- 10个步骤教你如何安装Anaconda安装,Python数据分析入门必看
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:小白 PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行 ...
- docker 概览 (1)
Docker Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化.容器是完全使 ...
- W - Palindrome HDU - 1513
题目大意: 插入最少的字符,使原字符串成为回文串. 题解: LCS问题,将字符串反转,然后求这俩字符串的LCS,总长度减去LCS即可(多组输入). N最大是5E3,直接用二维数组会超内存.所以要用到滚 ...
- OkHttp 优雅封装 OkHttps 之 回调线程魔变
第一篇:OkHttp 优雅封装 HttpUtils 之 气海雪山初探 第二篇:OkHttp 优雅封装 HttpUtils 之 上传下载解密 简介 HttpUtils 从 v2.3.0 之后便重命名了, ...
- vue2.x学习笔记(二十一)
接着前面的内容:https://www.cnblogs.com/yanggb/p/12632730.html. 可复用性&结合-混入 基础 混入(mixin)提供了一种非常灵活的方式,来分发v ...
- jmeter事务控制器
jmeter事务控制器常用于压力测试时如果一个功能包括多个请求时,需要测试这个功能的压力情况,则需要把多个请求放到一个事务控制器里面
- ASP.NET Core 与 ASPOSE.Words for .NET
Aspose.Total是Aspose公司旗下的最全的一套office文档管理方案,它提供的原生API可以对Word.Excel.PDF.Powerpoint.Outlook.CAD.图片.3D.ZI ...
- 2019-2020-1 20199326《Linux内核原理与分析》第三周作业
第三周学习内容 庖丁解牛Linux内核分析第二章:操作系统是如何工作的 Linux内核分析实验二 学到的一些知识 计算机的三大法宝:存储程序计算机,函数调用堆栈,中断 堆栈是C语言程序运行时必须使用的 ...