当前位置: 首页 > news >正文

【洛谷】P1856

[IOI1998] 矩形周长Picture

#线段树 #数据结构

题目背景

墙上贴着许多形状相同的海报、照片。它们的边都是水平和垂直的。每个矩形图片可能部分或全部的覆盖了其他图片。所有矩形合并后的边长称为周长。

题目描述

编写一个程序计算周长。

如图 1 1 1 所示 7 7 7 个矩形。

如图 2 2 2 所示,所有矩形的边界。所有矩形顶点的坐标都是整数。

输入格式

输入文件的第一行是一个整数 N N N,表示有多少个矩形。接下来 N N N 行给出了每一个矩形左下角坐标和右上角坐标。

输出格式

输出文件只有一个正整数,表示所有矩形的周长。

样例 #1

样例输入 #1

7
-15 0 5 10
-5 8 20 25
15 -4 24 14
0 -6 16 4
2 15 10 22
30 10 36 20
34 0 40 16

样例输出 #1

228

提示

数据范围及约定

对于全部数据, 1 ≤ N < 5000 1 \le N<5000 1N<5000,所有坐标的数值范围都在 − 1 0 4 -10^4 104 1 0 4 10^4 104 之间。

思路

首先长度一定当前线段树维护的长度与上一次的距离,宽度就是两条扫描线之间的距离,但是需要判断有几条,也就是有几个并起来的块。

我们需要在原先的扫描线上添加一个左右覆盖的标记 l c o v e r lcover lcover r c o v e r rcover rcover,以及条数 s u m sum sum

答案就是 ∑ i = 1 i ≤ n ( l e n i − l e n i − 1 ) ) ∗ 2 + s u m ∗ a b s ( L i − L i − 1 ) \sum_{i=1}^{i\leq n} (len_i- len_{i-1}))* 2 +sum* abs(L_i - L_{i-1}) i=1in(lenileni1))2+sumabs(LiLi1)

代码

const int N = 1e5 + 10;struct line {int x1, x2, y;int tag; // 1/0 入边出边bool operator<(const line& l) const {return y < l.y;}
}L[N];#define ls(x) x<< 1 
#define rs(x) x<< 1 | 1  struct node {int l, r, cnt, len, sum, lcover, rcover;
}tree[N * 8];int X[N];void build(int p, int l, int r) {tree[p] = { l,r,0,0,0,0 };if (l == r) {return;}int mid = l + r >> 1;build(ls(p), l, mid);build(rs(p), mid + 1, r);
}void push_up(int p) {int l = tree[p].l, r = tree[p].r;if (tree[p].cnt) {tree[p].len = X[r + 1] - X[l];tree[p].sum = 2;tree[p].lcover = tree[p].rcover = 1;}else {tree[p].len = tree[ls(p)].len + tree[rs(p)].len;tree[p].sum = tree[ls(p)].sum + tree[rs(p)].sum;tree[p].lcover = tree[ls(p)].lcover;tree[p].rcover = tree[rs(p)].rcover;if (tree[ls(p)].rcover && tree[rs(p)].lcover) {tree[p].sum -= 2;}}
}void update(int p, int x, int y, int tag) {if (x <= tree[p].l && y >= tree[p].r) {tree[p].cnt += tag;push_up(p);return;}int mid = tree[p].l + tree[p].r >> 1;if (y <= mid) {update(ls(p), x, y, tag);}else if (x >= mid + 1) {update(rs(p), x, y, tag);}else {update(ls(p), x, y, tag);update(rs(p), x, y, tag);}push_up(p);
}void solve() {int n;std::cin >> n;for (int i = 1; i <= n; ++i) {int x1, y1, x2, y2;std::cin >> x1 >> y1 >> x2 >> y2;X[i] = x1; X[i + n] = x2;L[i] = { x1,x2,y1,1 }; L[i + n] = { x1,x2,y2,-1 };}n <<= 1;std::sort(X + 1, X + 1 + n);std::sort(L + 1, L + 1 + n);int m = std::unique(X + 1, X + 1 + n) - X - 1;build(1, 1, m - 1);ll res = 0, last = 0;for (int i = 1; i <= n - 1; ++i) {int l = std::lower_bound(X + 1, X + m + 1, L[i].x1) - X;int r = std::lower_bound(X + 1, X + m + 1, L[i].x2) - X;update(1, l, r - 1, L[i].tag);res += std::abs(tree[1].len - last);res += (ll)tree[1].sum * (ll)(L[i + 1].y - L[i].y);last = tree[1].len;}res += L[n].x2 - L[n].x1;std::cout << res << "\n";
}signed main() {std::ios::sync_with_stdio(0);std::cin.tie(0);std::cout.tie(0);int t = 1;//std::cin >> t;while (t--) {solve();}return 0;
}

http://www.mrgr.cn/news/54235.html

相关文章:

  • ruoyi域名跳转缓存冲突问题(解决办法修改:session名修改session的JSESSIONID名称)
  • AI大模型是否有助于攻克重大疾病?
  • filebeat接入nginx和mysql获取日志
  • Reverse.Kr—— 前四题
  • Ubuntu下解决python程序首次连接mysql拒绝访问之总结
  • RestTemplate 学习笔记
  • 【H2O2|全栈】WPS/Office系列有哪些好用的快捷方式?
  • Javaweb基础-axios
  • 学习虚幻C++开发日志——TSet
  • 推荐系统 # 二、推荐系统召回:协同过滤 ItemCF/UserCF、离散特征处理、双塔模型、自监督学习、多路召回、曝光过滤
  • MySQL 索引:优化数据库性能的关键
  • Java的重载和主要内存区
  • 开发工具(上)
  • [SAP ABAP] SE11定义数据类型(结构与表类型)
  • 模型轻量化1--模型剪枝
  • AI周报(10.13-10.19)
  • 把自己写的文章发布在各大媒体网站上难不难?
  • 【每日一题】【算法双周赛】【第 20 场 小白入门赛评价/分享】赛后另类AI写题分析分享
  • 2025年天津仁爱学院专升本动画化学工程与工艺专业对应专业限制
  • 《嵌入式最全面试题-Offer直通车》目录
  • Lua字符串
  • JDK 1.6主要特性
  • 我的JAVA项目构建
  • 怎么修改编辑PDF的内容,有这4个工具就行了。
  • MySQL-20.多表设计-一对一多对多
  • 解锁A/B测试:如何用数据驱动的实验提升你的网站和应用