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

UVa1472/LA4980 Hanging Hats

UVa1472/LA4980 Hanging Hats

  • 题目链接
  • 题意
    • 输入格式
    • 输出格式
  • 分析
  • AC 代码

题目链接

  本题是2010年icpc欧洲区域赛中欧赛区的H题

题意

  魔法师有 n 顶帽子需要依次悬挂在墙上。每顶帽子在挂好后都会变成一个底在地面上的等腰三角形。帽子分为窄帽子和宽帽子两种。窄帽子底面宽度等于帽尖(即悬挂点)的高度,而宽帽子的底面宽度等于帽尖高度的两倍。如果一顶帽子的帽尖包含在另一顶帽子里(内部或者边界上),它就是不可见的,反之就是可见的。你的任务是计算出悬挂每顶帽子后,可见帽子的数量。注意,如果悬挂点和已有帽子的帽尖重合,或者位于某个已有帽子的内部或者边界上,那么这顶帽子是挂不上的。
  如下图所示,帽尖上的数字代表挂的顺序(1 是最先挂的,7 是最后挂的),帽子 2 和 6 是窄帽子,其他是宽帽子。帽子 3 和 4 挂不上,而帽子 7 挂上之后,帽子1、2 和 7 是可见的。
Hanging Hats

输入格式

  输入第一行为数据组数 T(T≤30)。每组数据第一行为帽子的个数 n(1≤n≤100 000),以下 n 行每行包含两个整数 xi,yi(xi 是悬挂点的横坐标,yi 是高度)和一个字母 W 或者 N。

输出格式

  对于每顶帽子,输出悬挂后可见帽子的个数。如果挂不上这顶帽子,输出 FAIL。

分析

  对于宽帽子 xi,yix_i,y_ixi,yi,如果帽子 xj,yjx_j,y_jxj,yj 的帽尖在其内,则{yj≤yixj≥xi−(yi−yj)xj≤xi+(yi−yj)\left\{\begin{matrix} y_j\le y_i\\x_j\ge x_i - (y_i-y_j)\\ x_j\le x_i + (y_i-y_j)\end{matrix}\right.yjyixjxi(yiyj)xjxi+(yiyj){yj≤yiyj−xj≤yi−xiyj+xj≤yi+xi\left\{\begin{matrix} y_j\le y_i\\ y_j-x_j\le y_i - x_i\\ y_j+x_j\le y_i + x_i\end{matrix}\right.yjyiyjxjyixiyj+xjyi+xi可以发现只需要后两个不等式,因为它俩能推出第一个不等式。

  同样,对于窄帽子 xi,yix_i,y_ixi,yi,如果帽子 xj,yjx_j,y_jxj,yj 的帽尖在其内,则{yj−2xj≤yi−2xiyj+2xj≤yi+2xi\left\{\begin{matrix} y_j-2x_j\le y_i - 2x_i\\ y_j+2x_j\le y_i + 2x_i\end{matrix}\right.{yj2xjyi2xiyj+2xjyi+2xi
  因此可以对各个帽尖的坐标做这两种变换,将问题转化为区间问题(单点修改以及区间查询)。将每个帽尖坐标做两次变换构成两棵二维区间树(一棵是宽帽子形式、一棵是窄帽子)的离散点,区间树的每个结点维护两个数:宽帽子树的宽帽子总数(或者窄帽子树的窄帽子总数)sss、可见帽子数 vvv

  挂宽帽子 xi,yix_i,y_ixi,yi 时,查询宽帽子树区间 {[yi−xi,∞)[yi+xi,∞)\left\{\begin{matrix} \left [ y_i-x_i, \infty \right ) \\ \left [ y_i+x_i, \infty \right )\end{matrix}\right.{[yixi,)[yi+xi,) 内宽帽子总数 sss 是否大于 0:s>0s>0s>0 则无法悬挂;s=0s=0s=0 则修改宽帽子树区间 {(−∞,yi−xi](−∞,yi+xi]\left\{\begin{matrix} \left ( -\infty, y_i-x_i \right ] \\ \left ( -\infty, y_i+x_i \right ] \end{matrix}\right.{(,yixi](,yi+xi]内可见帽子数 v=0v=0v=0 再给点 (yi−xi,yi+xi)(y_i-x_i,y_i+x_i)(yixi,yi+xi) 进行修改 s+1,v+1s+1,v+1s+1,v+1,同时修改窄帽子树区间 {(−∞,yi−2xi](−∞,yi+2xi]\left\{\begin{matrix} \left ( -\infty, y_i-2x_i \right ] \\ \left ( -\infty, y_i+2x_i \right ] \end{matrix}\right.{(,yi2xi](,yi+2xi]内可见帽子数 v=0v=0v=0 再给点 (yi−2xi,yi+2xi)(y_i-2x_i,y_i+2x_i)(yi2xi,yi+2xi) 进行修改 v+1v+1v+1
  挂窄帽子 xi,yix_i,y_ixi,yi 时,查询窄帽子树区间 {[yi−xi,∞)[yi+xi,∞)\left\{\begin{matrix} \left [ y_i-x_i, \infty \right ) \\ \left [ y_i+x_i, \infty \right )\end{matrix}\right.{[yixi,)[yi+xi,) 内窄帽子总数 sss 是否大于 0 再类似处理即可。

  可惜题目数据规模很大,用二维线段树动态开点的话,修改宽帽子树区间 {(−∞,yi−xi](−∞,yi+xi]\left\{\begin{matrix} \left ( -\infty, y_i-x_i \right ] \\ \left ( -\infty, y_i+x_i \right ] \end{matrix}\right.{(,yixi](,yi+xi]内可见帽子数 v=0v=0v=0 以及修改窄帽子树区间 {(−∞,yi−2xi](−∞,yi+2xi]\left\{\begin{matrix} \left ( -\infty, y_i-2x_i \right ] \\ \left ( -\infty, y_i+2x_i \right ] \end{matrix}\right.{(,yi2xi](,yi+2xi]内可见帽子数 v=0v=0v=0 这里由于要找到每个可见的帽子再进行点修改,时间开销有点夸张,提交会超时。

  上 k-D Tree 的话,整体时间开销小一些,提交仍然超时。考虑到对每顶帽子,进行坐标转换后其实是要查询以某点为左下角的矩形区间然后在查询结果为 0 时修改以此点为右上角的矩形区间内每一个点。可以参照 k-D Tree 的思路将区间树构造成四叉树的形式:每个子区间树首先选择一个点 pip_ipi (取中位数处的点),然后区间内其他点 pjp_jpj 按照在点 pip_ipi 的左下{xj<xiyj<yi\left\{\begin{matrix} x_j<x_i \\ y_j<y_i \end{matrix}\right.{xj<xiyj<yi、左上{xj<xiyj≥yi\left\{\begin{matrix} x_j<x_i \\ y_j \ge y_i \end{matrix}\right.{xj<xiyjyi、右下{xj≥xiyj<yi\left\{\begin{matrix} x_j\ge x_i \\ y_j < y_i \end{matrix}\right.{xjxiyj<yi、右上{xj≥xiyj≥yi\left\{\begin{matrix} x_j\ge x_i \\ y_j \ge y_i \end{matrix}\right.{xjxiyjyi四个象限划分成四个子树。由于四个子树内点的坐标大小按象限划分明确,这将给查询操作提供便利,时间开销得到优化,这一版提交AC了。

  官方题解说最优思路是采用优先查找树(Priority Search Tree),整体时间复杂度才O(nlog⁡n)O(n\log n)O(nlogn),后面实践一把再补上。

AC 代码

#include <iostream>
#include <algorithm>
using namespace std;#define N 100010
long long x[N], y[N], *px, *py; int a[N], rm[N], n, c; bool w[N];bool cmpx(int i, int j) {return px[i] < px[j];
}bool cmpy(int i, int j) {return py[i] < py[j];
}struct {long long x[N], y[N]; int l1[N], l2[N], r1[N], r2[N], f[N], s[N], v[N], p[N], q[N], t;void build(int& o, int l, int r) {if (!o) o = ++t, l1[o] = l2[o] = r1[o] = r2[o] = f[o] = s[o] = v[o] = 0;if (l+1 < r) {sort(a+l, a+r, cmpx);int m = lower_bound(a+l, a+r, a[(l+r)>>1], cmpx) - a;sort(a+l, a+m, cmpy);int c = lower_bound(a+l, a+m, a[m], cmpy) - a;if (l < c) build(l1[o], l, c);if (c < m) build(l2[o], c, m);if (m+1 < r) {sort(a+m+1, a+r, cmpy);c = lower_bound(a+m+1, a+r, a[m], cmpy) - a;if (m+1 < c) build(r1[o], m+1, c);if (c < r) build(r2[o], c, r);}p[q[a[m]] = o] = a[m]; f[l1[o]] = f[l2[o]] = f[r1[o]] = f[r2[o]] = o;} else p[q[a[l]] = o] = a[l];}void build() {l1[0] = l2[0] = r1[0] = r2[0] = s[0] = v[0] = t = c = 0; px = x; py = y; build(c, 0, n);}bool query(int o, int i) {if (s[o] == 0) return false;if (x[i] <= x[p[o]]) {if (y[i] > y[p[o]]) return query(r2[o], i) || query(l2[o], i);return s[o] - s[l1[o]] - s[l2[o]] - s[r1[o]] > 0 || query(r1[o], i) || query(l2[o], i) || query(l1[o], i);} else if (y[i] > y[p[o]]) return query(r2[o], i);return query(r2[o], i) || query(r1[o], i);}void rem(int o) {if (v[o] - v[l1[o]] - v[l2[o]] - v[r1[o]] - v[r2[o]] > 0) rm[c++] = p[o];if (v[l1[o]] > 0) rem(l1[o]);if (v[l2[o]] > 0) rem(l2[o]);if (v[r1[o]] > 0) rem(r1[o]);if (v[r2[o]] > 0) rem(r2[o]);}void qrm(int o, int i) {if (v[o] == 0) return;if (x[i] >= x[p[o]]) {if (y[i] >= y[p[o]]) {if (v[o] - v[l1[o]] - v[l2[o]] - v[r1[o]] - v[r2[o]] > 0) rm[c++] = p[o];rem(l1[o]); qrm(l2[o], i); qrm(r1[o], i); qrm(r2[o], i);} else qrm(l1[o], i), qrm(r1[o], i);} else if (y[i] >= y[p[o]]) qrm(l1[o], i), qrm(l2[o], i);else qrm(l1[o], i);}void add(int i, int d) {if (d) c = 0, qrm(1, i);for (int o = q[i]; o; o = f[o]) ++v[o], s[o] += d;}void remove(int i) {for (int o = q[i]; o; o = f[o]) --v[o];}
} t1, t2;void solve() {cin >> n;for (int i=0; i<n; ++i) {char c; cin >> x[i] >> y[i] >> c; w[i] = c == 'W'; a[i] = i;t1.x[i] = y[i]-x[i]; t1.y[i] = y[i]+x[i]; t2.x[i] = y[i]-2*x[i]; t2.y[i] = y[i]+2*x[i];}t1.build(); t2.build();for (int i=0; i<n; ++i)if (t1.query(1, i) || t2.query(1, i)) {cout << "FAIL" << endl;} else {t1.add(i, w[i]); t2.add(i, !w[i]);while (c--) t1.remove(rm[c]), t2.remove(rm[c]);cout << t1.v[1] << endl;}
}int main() {ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);int t; cin >> t;while (t--) solve();return 0;
}
http://www.xdnf.cn/news/18611.html

相关文章:

  • webpack开发模式与生产模式(webpack --mode=development/production“, )
  • ubuntu使用fstab挂载USB设备(移动硬盘)
  • Jenkins用户授权管理 企业级jenkins授权策略 jenkins用户权限分配
  • 【go语言】使用Wails开发一款现代化文本编辑器 - 从0到1的实践指南
  • 机器学习之线性回归:原理、实现与实践
  • 动态代理保姆级别
  • 移动应用青少年模式开发成本解析:原生、Flutter与Uniapp方案对比-优雅草卓伊凡
  • Slither 审计自己写的智能合约
  • MySQL InnoDB记录存储结构深度解析
  • 服务发现实例和服务实例是不同的
  • reactive 核心要点
  • Unreal Engine UPrimitiveComponent
  • 数据分析编程第二步: 最简单的数据分析尝试
  • day58 拓扑排序 (kama117. 软件构建) dijkstra(朴素版)(kama47. 参加科学大会)
  • 无人机电机与螺旋桨的匹配原理及方法(一)
  • JavaSSM框架从入门到精通!第三天(MyBatis(二))!
  • Python训练营打卡Day40-简单CNN
  • 【51单片机数码管字符左移】2022-11-11
  • 如何低门槛自制Zigbee 3.0温湿度计?涂鸦上新开发包,开箱即用、完全开源
  • 开源AI编程工具Kilo Code的深度分析:与Cline和Roo Code的全面对比
  • Tiger任务管理系统-13
  • 【jar包启动,每天生成一个日志文件】
  • Unity UnityWebRequest高级操作
  • Ubuntu部署K8S集群
  • Jmeter+Jenkins接口压力测试持续集成
  • 【motion】基于标签重合度的匹配算法1:原理
  • 3D打印小批量低成本打印玩具工艺品模型-中科米堆CASAIM
  • 字节Seed-OSS开源,不卷参数卷脑子
  • 从零开始搭 Linux 环境:VMware 下 CentOS 7 的安装与配置全流程(附图解)
  • 如何修复“DNS服务器未响应”错误