博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HDU 1828 Picture
阅读量:5079 次
发布时间:2019-06-12

本文共 3254 字,大约阅读时间需要 10 分钟。

HDU_1828

    以前只用离散化的思想写过这个题,现在又结合上线段树重新写了一遍。如果希望只沿一个方向扫描一遍就求出周长的话,那么相当于需要用两种方式分别求水平和竖直部分的周长。比如我们沿x方向扫描,那么竖直方向上的边长就需要通过矩形覆盖扫描线的总长度的变化值来计算,而水平方向上的边长就需要用点数乘以区间跨度去计算。

    其实感觉也可以在两个方法中任选一个,分别沿x、y方向各扫描一遍,也可以求出最后的周长。

    此外,如果我们沿x方向扫描,并按矩形覆盖的扫描线的总长度的变化值去计算竖直部分的边长的话,那么最初在对线段排序时,同一x值的线段一定要是矩形右边的边在前,是矩形左边的边在后。也就是说同一x位置上,要先进行添加边的操作,再进行删除边的操作,这是因为如果两条竖直边重合或有公共部分的话,我们如果先删再添就会多计算一部分长度。

#include
#include
#include
#define MAXD 10010 int N, M, ty[4 * MAXD], num[4 * MAXD], lc[4 * MAXD], rc[4 * MAXD], len[4 * MAXD], cnt[4 * MAXD]; struct Seg {
int x, y1, y2, col; }seg[4 * MAXD]; int cmps(const void *_p, const void *_q) {
Seg *p = (Seg *)_p, *q = (Seg *)_q; if(p->x == q->x) return p->col > q->col ? -1 : 1; return p->x < q->x ? -1 : 1; } int cmpy(const void *_p, const void *_q) {
int *p = (int *)_p, *q = (int *)_q; return *p < *q ? -1 : 1; } void build(int cur, int x, int y) {
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; len[cur] = lc[cur] = rc[cur] = num[cur] = cnt[cur] = 0; if(x == y) return ; build(ls, x, mid); build(rs, mid + 1, y); } void update(int cur, int x, int y) {
int ls = cur << 1, rs = (cur << 1) | 1; if(cnt[cur]) {
len[cur] = ty[y + 1] - ty[x]; lc[cur] = rc[cur] = 1; num[cur] = 2; } else if(x == y) len[cur] = lc[cur] = rc[cur] = num[cur] = 0; else {
len[cur] = len[ls] + len[rs]; lc[cur] = lc[ls], rc[cur] = rc[rs]; num[cur] = num[ls] + num[rs]; if(rc[ls] && lc[rs]) num[cur] -= 2; } } void init() {
int i, j, k, x1, y1, x2, y2; for(i = 0; i < N; i ++) {
scanf("%d%d%d%d", &x1, &y1, &x2, &y2); j = i << 1, k = (i << 1) | 1; seg[j].x = x1, seg[k].x = x2; seg[j].y1 = seg[k].y1 = y1, seg[j].y2 = seg[k].y2 = y2; seg[j].col = 1, seg[k].col = -1; ty[j] = y1, ty[k] = y2; } N <<= 1; qsort(seg, N, sizeof(seg[0]), cmps); qsort(ty, N, sizeof(ty[0]), cmpy); M = -1; for(i = 0; i < N; i ++) if(i == 0 || ty[i] != ty[i - 1]) ty[++ M] = ty[i]; build(1, 0, M - 1); } void refresh(int cur, int x, int y, int s, int t, int c) {
int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; if(x >= s && y <= t) {
cnt[cur] += c; update(cur, x, y); return ; } if(mid >= s) refresh(ls, x, mid, s, t, c); if(mid + 1 <= t) refresh(rs, mid + 1, y, s, t, c); update(cur, x, y); } int BS(int y) {
int mid, min = 0, max = M + 1; for(;;) {
mid = (min + max) >> 1; if(mid == min) break; if(ty[mid] <= y) min = mid; else max = mid; } return mid; } void solve() {
int i, j, k, ans, prelen; ans = prelen = 0; seg[N].x = seg[N - 1].x; for(i = 0; i < N; i ++) {
j = BS(seg[i].y1), k = BS(seg[i].y2); refresh(1, 0, M - 1, j, k - 1, seg[i].col); ans += num[1] * (seg[i + 1].x - seg[i].x); ans += abs(len[1] - prelen); prelen = len[1]; } printf("%d\n", ans); } int main() {
while(scanf("%d", &N) == 1) {
init(); solve(); } return 0; }

 

转载于:https://www.cnblogs.com/staginner/archive/2012/04/09/2438320.html

你可能感兴趣的文章
vim-DrawIt
查看>>
如何用Fiddler手机抓包
查看>>
学好Mac常用命令,助力iOS开发
查看>>
rac one node在线relocation
查看>>
2565放大的X(hdu)
查看>>
重温数据结构系列随笔:单链表(c#模拟实现)
查看>>
读取线图层上的点,输出为点图层
查看>>
pku 1840 Eqs 哈希处理
查看>>
ucos任务优先级从64到256,任务就绪表的改变
查看>>
//C#中的访问数据符
查看>>
217. Contains Duplicate
查看>>
vue2.0 关于Vue实例的生命周期
查看>>
小小SQLServer,你懂的
查看>>
Spring系列之Spring常用注解总结
查看>>
Xamarin.Forms的ActivityIndicator和ProgressBar比较
查看>>
jenkins 更换主数据目录
查看>>
Silverlight中恼人的g.i.cs错误
查看>>
SQLite 数据库增删改查
查看>>
<s:iterator>的status
查看>>
C++入门--1.0输入输出
查看>>