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

(思维)洛谷 P3081 USACO13MAR Hill Walk 题解

题意

N(1≤N≤105)N(1 \le N \le 10 ^ 5)N(1N105)座小山,每座山所占的区域用直线 (x1,y1)(x1, y1)(x1,y1)(x2,y2)(x2, y2)(x2,y2) 来表示(x1<x2x1 < x2x1<x2 并且 y1<y2y1 < y2y1<y2)。也就是说这些山用笛卡尔坐标系里的线段来表示,这些用于表示小山的线段都没有任何交点,第一座山的一端位于 (x1,y1)=(0,0)(x1, y1) = (0,0)(x1,y1)=(0,0)

贝西从 (0,0)(0,0)(0,0) 开始在第一座山上漫步,一旦贝西到了一座山,她会一直走到该山的终点,这时,她会从边缘处起跳,如果她降落到另一座山上,她会继续在新的山上漫步。贝西起跳后沿 yyy 轴方向下落,如果贝西不能降落到一座山上,她会一直下落,直到到达 yyy 轴的负无穷大位置(y=−∞y = -\infiny=)。

每座用线段表示的山 (x1,y1)→(x2,y2)(x1, y1) \to (x2, y2)(x1,y1)(x2,y2) 包含 (x1,y1)(x1, y1)(x1,y1) 这个点,但不包含 (x2,y2)(x2, y2)(x2,y2),请计算出贝西总共在多少座山上漫步了。

x1,y1,x2,y2≤109x1,y1,x2,y2\le 10^9x1,y1,x2,y2109

思路

因为线段没有交点,所以漫步路径是唯一的走完一座山之后,将会下到哪座山是固定的

有线段想用李超线段树。但是走到一座山的终点的时候,无法确定具体哪一座山峰:可能头顶有一座,哪怕没有李超树也只能返回终点的 yyy删线段?不会捏。

本质还是模拟漫步过程。我们记下每座山的起点终点信息,每到一座山的起点就把山加进 set 里(set 支持 O(log⁡n)O(\log n)O(logn)查询和删除)。记录当前登山编号 nownownow,初始时 now=1now=1now=1

我们每走到山 nownownow 的终点,就要下山。走完一座山之后,将会下到哪座山是固定的,即每座山的“前继”是固定的,我们想要 set 的指针前移就能走到对应的山。

首先,若遍历到一个终点不是 nownownow 的终点,就应该把当前点所在山删掉,以免影响下山。其次,我们想要找到一个排序规则,使 set 按照这个顺序将山峰从高到低排好序。

排序规则:比较 a,ba,ba,b 的上下关系,可以借助二者终点连线 ccc 来比较,如下图已清晰说明。
在这里插入图片描述

  • a.xb<b.xba.xb<b.xba.xb<b.xb 时:

    1. kb<kck_b<k_ckb<kc 时,a<ba<ba<b(如 a1,b,c1a1,b,c1a1,b,c1);
    2. 反之 kc<kbk_c<k_bkc<kb 时,b<ab<ab<aaaa 可以落到 bbb(如 a2,b,c2a2,b,c2a2,b,c2)。

    不用 a,ca,ca,c 比较的反例,如 a2′a2'a2 所示。

  • a.xb>b.xba.xb>b.xba.xb>b.xb 时:

    1. kc<kak_c<k_akc<ka 时,a<ba<ba<b(如 a1,b,c1a1,b,c1a1,b,c1);
    2. 反之 ka<kck_a<k_cka<kc 时,b<ab<ab<abbb 可以落到 aaa(如 a2,b,c2a2,b,c2a2,b,c2)。

    不用 a,ba,ba,b 比较的反例,如 b′b'b 所示。

dd slope(dd xa,dd ya,dd xb,dd yb)
{return (ya-yb)/(xa-xb);
}
bool operator < (hill a,hill b)//a<b,b在a上 
{dd ka=slope(a.xa,a.ya,a.xb,a.yb);dd kb=slope(b.xa,b.ya,b.xb,b.yb);dd kc=slope(a.xb,a.yb,b.xb,b.yb);if(a.xb<b.xb)return kb<kc;return kc<ka;
}

在 set 上获取直接前继,可以用指针移动。

储存起点和终点,记得开 222 倍空间。

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define dd double
const ll N=2e5+9;
ll n;
struct hill
{dd xa,ya,xb,yb;ll id;
}b[N];
dd slope(dd xa,dd ya,dd xb,dd yb)
{return (ya-yb)/(xa-xb);
}
bool operator < (hill a,hill b)//a<b,b在a上 
{dd ka=slope(a.xa,a.ya,a.xb,a.yb);dd kb=slope(b.xa,b.ya,b.xb,b.yb);dd kc=slope(a.xb,a.yb,b.xb,b.yb);if(a.xb<b.xb)return kb<kc;return kc<ka;
}
set<hill>S;
struct point
{dd x,y;ll id;
}P[N<<1];
bool cmp(point x,point y)
{if(x.x!=y.x)return x.x<y.x;return x.y<y.y;
}
int main()
{scanf("%lld",&n);for(int i=1;i<=n;i++){dd xa,ya,xb,yb;scanf("%lf%lf%lf%lf",&xa,&ya,&xb,&yb);b[i]=(hill){xa,ya,xb,yb,i};P[i*2-1]=(point){xa,ya,i};P[i*2]=(point){xb,yb,i};}S.insert(b[1]);sort(P+1,P+2*n+1,cmp);ll ans=1,now=1;for(int i=2;i<=n*2;i++){ll id=P[i].id;if(b[id].xa==P[i].x)//起点{S.insert(b[id]);continue;}if(now!=id)S.erase(b[id]);//没走到遍历的这座山else {set<hill>::iterator B=S.find(b[id]);//走到终点了 if(B==S.begin())break;//无山可走B--,now=B->id;//下山 ans++;}}printf("%lld",ans);return 0;
}
http://www.dtcms.com/a/273393.html

相关文章:

  • 网络安全基础概念以及虚拟环境的搭建
  • alpinelinux的网络配置
  • ZW3D 二次开发-创建六面体方框
  • 力扣面试150题--全排列
  • AOSP自启动拦截框架Intent Firewall
  • 反向传播notes
  • 敏捷测试中的质量闸门如何设置?
  • 位运算算法题
  • 第七讲:C++中的string类
  • 深度学习参数初始化方法详解及代码实现
  • 深度学习×第7卷:参数初始化与网络搭建——她第一次挑好初始的重量
  • ZW3D 二次开发-创建椭球体
  • 灰度发布策略制定方案时可以参考的几个维度
  • 递推+高精度加法 P1255 数楼梯
  • apt -y参数的含义
  • 计算机视觉 之 数字图像处理基础(一)
  • Kubernetes 1.23.6 kube-scheduler 默认打分和排序机制详解
  • 多商户商城系统源码选型指南:开源 vs 定制,哪种更适合?
  • 救回多年未用kubeadm搭建的kubernetes集群
  • 5. isaac sim4.2 教程-Core API-操作机械臂
  • 用黑盒测试与白盒测试,读懂专利审查的 “双重关卡”​​
  • K8S的CNI之calico插件升级至3.30.2
  • 深度学习中的 Seq2Seq 模型与注意力机制
  • 解释sync.WaitGroup的用途和工作原理。在什么情况下应该使用它?
  • 时间显示 蓝桥云课Java
  • Android ViewBinding 使用与封装教程​​
  • Netron的基本使用介绍
  • UNet改进(20):融合通道-空间稀疏注意力的医学图像分割模型
  • 客户频繁问询项目进度,如何提高响应效率
  • Java 中的多线程实现方式