HDOJ-1542 Atlantis 扫描线

2023-12-12 20:40
文章标签 扫描线 atlantis hdoj 1542

本文主要是介绍HDOJ-1542 Atlantis 扫描线,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

扫描线算法的核心思想在于使用线段树对扫描线线段的长度进行维护。因此,如果平行于x轴做扫描线,那么就需要以所有的端点的x坐标为端点,以这些端点组成的线段为线段树叶子节点存储的对象,从而对扫描线的长度进行维护。

另外,说明下代码中cnt的作用。这个标记代表看似是一个lazy tag,但又不是,因为这个标记是不会往子节点传的(及不能使用pushdown操作)。扫描线算法中,叶子节点(代表的是每一个小段)和非叶子节点(代表几个小段的拼接)的cnt值是独立的,代表的按照线段树的分法,恰好被完全覆盖的次数(前提是父节点没有被完全覆盖)。因此,如果当前节点的cnt值为0了,至要它还有子节点,它的sum依然可以由子节点求和得到(虽然整段覆盖的没有了,但还可能在这个区间中有部分的覆盖存在)。

下图为cnt的作用。图了颜色代表cnt加了1.

#include <bits/stdc++.h>using namespace std;
using ll = long long;
const int INF = 2e9;
const int MAXN = 2e5+5;struct line {double x1, x2, y;int flag;line(){}line(double x1, double x2, double y, int flag){this->x1 = x1, this->x2 = x2, this->y = y; this->flag = flag;}friend bool operator < (const line &a, const  line &b){return a.y < b.y;} 
};vector<double> sum(MAXN << 3, 0);
vector<int> cnt(MAXN << 3, 0);line lines[MAXN <<1];
double P[MAXN<<1];void pushUp(int id, int l, int r){if(cnt[id]){ sum[id] = P[r] - P[l - 1];}//后面都是cnt为0的情况,cnt为1代表区域中所有的边都被选中else if(r == l) sum[id] = 0;  //只有一段,那么就直接这一段为0else {       //有多段,那么这多段为后续节点的求和sum[id] = sum[id << 1] + sum[id << 1|1];}
}void update(int id, int l, int r, int L, int R, int flag){if(L <=l && r <= R){cnt[id] += flag;pushUp(id, l, r);return;}int mid = (l + r) >> 1;if(L <= mid){update(id << 1, l, mid, L, R, flag);}if(R > mid){update(id << 1|1, mid+1, r, L, R, flag);}pushUp(id, l, r);return;
}signed main(){int n; double x1, y1, x2, y2;int ca = 1;while(true){double ans=0;for(int i = 0; i < sum.size(); i++){sum[i]=0; cnt[i]=0;}scanf("%d", &n); if(n==0) break;for(int i = 0; i < n; i++){scanf("%lf %lf %lf %lf",&x1, &y1, &x2, &y2);lines[i*2] = line(x1, x2, y1, 1);lines[i*2+1] = line(x1, x2, y2, -1);             P[i*2] = x1;P[i*2+1] = x2;}sort(lines, lines+2*n);sort(P, P+2*n);int d = unique(P, P+2*n) - P; //实际不重合的端点数目for(int i = 0; i < n * 2 -1; i ++){int l = lower_bound(P, P+d, lines[i].x1) - P + 1;int r = lower_bound(P, P+d, lines[i].x2) - P + 1;update(1, 1, d-1, l, r-1, lines[i].flag);ans += sum[1] * (lines[i+1].y - lines[i].y);}printf("Test case #%d\nTotal explored area: %.2lf\n\n", ca++, ans);}return 0;
}

 

这篇关于HDOJ-1542 Atlantis 扫描线的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/485871

相关文章

洛谷P5490扫描线

0是最小的数字,将一个线段看成一个区间,对于一个矩形,从下扫到上,入边为1,而出边为-1,意思是将这个区间上的所有点加1(区间修改).把线段表示为Line[i],其中记录了l,r,h,tag,左右端点,高度,入边还是出边(1或-1) 那么每次区间修改后不为0的区间它的值可能是1,2,3或者是其它数字,这不好统计,可以将它转化一下,0是不是表示没有被覆盖过的地方,我们只要统计0的个数然后用总长减去

Zxing扫描二维码精简(竖屏、拉伸处理、扫描框大小和扫描线移动、开灯)

自己在简版zxing的基础上美化了下,给大家分享下,直接扫描功能没问题。 就是从相册导入图片,解码一直不成功,导入图片解码 我引入了一个解码类  RGBLuminanceSource(百度网上二维码图片解码都是这个,我还把这个类编译了,导到core.jar包里面了), 好像是hity类型有问题,反正一直不成功。 有大神解决了,回复告诉我!谢谢! 分享 暂时没做效

扫描线Sweep Line算法总结

扫描线算法,推荐还是用标准的模板去写,treemap只适合于求最大的overlap个数的题目,其余的不能用treemap来解,所以推荐还是用event的思想去+1, -1然后排序扫描的方法可以用来解所有的题型; Number of Airplanes in the Sky 思路:经典扫描线算法:把interval起飞和降落做为event,全部打散,按照时间排列,同时时间相等的,按照降落在前面,起

矩形面积并、矩形面积交、矩形周长并(线段树、扫描线总结)

转自:http://blog.csdn.net/lwt36/article/details/48908031 HDU 1542 [POJ 1151] Atlantis (矩形面积并) 题意: 求N<=100个矩形的面积并 分析: 离散化: 这些技巧都是老生常谈的了, 不然浮点数怎么建树, 离散化 x 坐标就可以了扫描线: 首先把矩形按 y 轴分成两条边, 上边和下边,

【HDU1255】【线段树】【扫描线】【面积】

覆盖的面积 Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4417    Accepted Submission(s): 2180 Problem Description 给定平面上若干矩形,求出被这些矩形覆

hdoj 2371 decoded string. Decode the Strings

http://acm.hdu.edu.cn/showproblem.php?pid=2371 题意:给出编码的原则,给一个字符串,输出该字符串经过m次解码后的字符串。 啊啊啊啊。。。。无耻的看错题意了,以为给出字符串输出经过m次解码的后的字符串,样例死活过不了,赛后才发现问的是“decoded string”. 即解码后的字符串。。 思路:对于 5 3 2 3 1 5 4 helol

poj2482--Stars in Your Window(扫描线)

题目链接:点击打开链接 链接题目大意:给出n个星星的坐标,每个星星有一个亮度,给出一个矩形的长和宽,问矩形能包括的星星的最大亮度和(不包括边框)。 假设每个星星都是矩形的最左下点,那么每一个星星都可以得到一个矩形,(x,y)->(x,y,x+w,y+h),这个矩形的两条高边的值也就是星星的亮度k和-k,对于不同的矩形来说,如果高线出现重合部分,那么也就是说这两个星是可以出现在同一个矩形中的,扫

HDOJ 1874 畅通工程续——结构体模拟邻接链表的SPFA算法

Problem Description 某省自从实行了很多年的畅通工程计划后,终于修建了很多路。不过路多了也不好,每次要从一个城镇到另一个城镇时,都有许多种道路方案可以选择,而某些方案要比另一些方案行走的距离要短很多。这让行人很困扰。 现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。   Input 本题目包含多组数据,请处理到文

HDU 1828 POJ 1177 Picture(线段树+扫描线+离散化)

HDU题目地址:HDU 1828  POJ题目地址:POJ 1177 这题是求周长并,我用的方法可能有点麻烦。。是先求横着的线,再求竖着的线。每次只要求出每次的总区间覆盖长度,然后每次累加这次的总区间覆盖与上次的总区间覆盖长度的差的绝对值。因为只有长度发生变化时,才会产生一段新的周长。 待会再试试只扫描一次的方法。此博客有待更新。 代码如下: #include <iostream>#

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题。。稍微处理一下然后用求面积并的方法求即可。 代码如下: #include <iostream>#include <cstdio>#include <string>#include <cstring>#include <stdlib.h>#include <math.h>#include <ctype.h>#include <queue>#