Mountainous landscape
Description
现在在平面上给你一条折线 \(P_1P_2 \cdots P_n\) 。 \(x\) 坐标是严格单调递增的。对于每一段折线 \(P_iP_{i+1}\) ,请你找一个最小的 \(j\) ,使得 \(j \gt i\) 且CJB走在 \(P_iP_{i+1}\) 上能看到折线 \(P_jP_{j+1}\) 的任何一个点。注意,CJB的高度无限趋于0但不可忽略。也就是说,请找一条编号最小的折线 \(P_jP_{j+1}\) 使得 \(j \gt i\) 且线段 \(P_jP_{j+1}\)相交。
Solution
首先手玩。
考虑每一条射线\(\alpha=(P_i,P_{i+1})\)的答案,其实就是最小的\(j\),满足\(j>i\)且\(P_{j+1}\)严格在该射线上方。
有效的、需要考虑的\(P_{j+1}\),一定在由\((i,n]\)这些点构成的凸包上。我们相当于要判定一条射线\(\alpha\)与凸包是否有交,并找到交线的具体位置。
第一个问题很好解决,二分凸包上最逼近射线\(\alpha\)斜率的点,若其在射线上方则凸包与射线有交,否则直接无解。
关键是第二个问题。我们知道射线与凸包有交,甚至可以知道具体是哪一条凸包边与射线相交,却不知道是哪一条原边与射线有交,无法输出答案。我们发现这个凸包的信息已经不足以解决我们的问题了,但我们可以二分继续做:如果按相同方法判定左凸包也与射线有交,那么显然答案在左边,递归左凸包计算,并返回其的答案;否则,只能到右凸包里寻找答案。
单次询问复杂度\(\mathcal O(log^2)\)。
关键思路是无法确定具体方案的时候,考虑利用存在性二分答案。另一个Tips是有关线段树的二分问题,不要总想着用二分套线段树,而应该想想能否用线段树上二分,后者一般是两个\(log\),而前者是三个\(log\)。
Code
#include <cstdio>
#include <vector>
#define pb push_back
using namespace std;
namespace IO{
const int S=10000005;
char buffer[S];
int pos;
void Load(){
pos=0;
fread(buffer,1,S,stdin);
}
char getChar(){
return buffer[pos++];
}
int getInt(){
int x=0,f=1;
char c=getChar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getChar();}
while('0'<=c&&c<='9'){x=x*10+c-'0';c=getChar();}
return x*f;
}
}
using IO::getInt;
const int N=100005;
const double EPS=1e-6;
typedef long long ll;
typedef vector<int> vi;
int n;
struct Dot{ int x,y; }a[N];
bool slope_dec(int i,int j,int k){
return 1ll*(a[j].y-a[i].y)*(a[k].x-a[j].x)>1ll*(a[j].x-a[i].x)*(a[k].y-a[j].y);
}
double slope(int i,int j){
return 1.0*(a[j].y-a[i].y)/(a[j].x-a[i].x);
}
void getline(int i,int j,double &k,double &b){
k=slope(i,j);
b=a[i].y-k*a[i].x;
}
namespace SEG{
const int S=N*2;
int rt,sz;
int ch[S][2];
vi hull[S];
int top[S];
double k,b;
void build(int &u,int l,int r){
u=++sz;
hull[u]=vi(r-l+2);
top[u]=0;
for(int i=l;i<=r+1;i++){
while(top[u]>=2&&!slope_dec(hull[u][top[u]-2],hull[u][top[u]-1],i))
top[u]--;
hull[u][top[u]++]=i;
}
hull[u].resize(top[u]);
if(l==r)
return;
int mid=(l+r)>>1;
build(ch[u][0],l,mid);
build(ch[u][1],mid+1,r);
}
void set(double _k,double _b){
k=_k;
b=_b;
}
int find(int u){
int l=0,r=top[u]-2,mid;
while(l<=r){
int mid=(l+r)>>1;
if(slope(hull[u][mid],hull[u][mid+1])>k)
l=mid+1;
else
r=mid-1;
}
int who=hull[u][r+1];
return (k*a[who].x+b+EPS<=a[who].y)?who-1:0;
}
int query(int u,int l,int r,int L,int R){
int mid=(l+r)>>1;
if(L<=l&&r<=R){
if(l==r)
return find(u);
if(!find(u))
return 0;
if(find(ch[u][0]))
return query(ch[u][0],l,mid,L,R);
else
return query(ch[u][1],mid+1,r,L,R);
}
if(R<=mid)
return query(ch[u][0],l,mid,L,R);
else if(mid<L)
return query(ch[u][1],mid+1,r,L,R);
else{
int left=query(ch[u][0],l,mid,L,mid);
if(left)
return left;
return query(ch[u][1],mid+1,r,mid+1,R);
}
}
}
void readData(){
n=getInt();
for(int i=1;i<=n;i++)
a[i].x=getInt(), a[i].y=getInt();
}
void solve(){
for(int i=1;i<n;i++)
if(i<=n-2){
double k,b;
getline(i,i+1,k,b);
SEG::set(k,b);
printf("%d ",SEG::query(SEG::rt,1,n-1,i+1,n-1));
}
else
printf("0 ");
puts("");
}
int main(){
IO::Load();
readData();
SEG::build(SEG::rt,1,n-1);
solve();
return 0;
}
Mountainous landscape的更多相关文章
- BZOJ4049 [Cerc2014] Mountainous landscape
首先对于一个给定的图形,要找到是否存在答案非常简单... 只要维护当然图形的凸包,看一下是否有线段在这条直线上方,直接二分即可,单次询问的时间复杂度$O(logn)$ 现在用线段树维护凸包,即对于一个 ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- NOIp2018模拟赛三十五
两道大数据结构把我砸懵 成绩:未提交 Orz xfz两道正解 A:[BZOJ4049][CREC2014B]mountainous landscape B:CJB的大作(CF改编题)
- SAP SLT (Landscape Transformation) 企业定制培训
No. Item Remark 1 SAP SLT概述 SAP Landscape Transformation Overview 2 SAP SLT 安装与配置<1> for abap ...
- iPad apple-touch-startup-image实现portrait和landscape
iPad apple-touch-startup-image实现portrait和landscape 为ipad制作web应用程序的启动画面时发现个问题,只能显示竖屏图,横屏图出不来,网上的朋友都说无 ...
- JS 获取和监听屏幕方向变化(portrait / landscape)
移动设备的屏幕有两个方向: landscape(横屏)和portrait(竖屏),在某些情况下需要获取设备的屏幕方向和监听屏幕方向的变化,因此可以使用Javascript提供的 MediaQueryL ...
- [JS代码]如何判断ipad或者iphone是否为横屏或者竖屏 - portrait或者landscape
//判断横屏或者竖屏 function orient() { //alert('gete'); if (window.orientation == 0 || window.orientation == ...
- iOS的横屏(Landscape)与竖屏(Portrait)InterfaceOrientation
http://www.molotang.com/articles/1530.html 接着上篇写的触摸事件,这次借机会整理下iOS横屏和竖屏的翻转方向支持,即InterfaceOrientation相 ...
- CNCF CloudNative Landscape
cncf landscape CNCF Cloud Native Interactive Landscape 1. App Definition and Development 1. Database ...
随机推荐
- python_基础硬件知识
通过学习这一篇章的内容,回顾了<数字逻辑><计算机组成原理><操作系统> 这几门课的相关知识 有时候,总是要了解一些基本,才能更容易理解程序 以下是我的一些听课记录 ...
- MySQL学习笔记04 插入中文时出现ERROR 1366 (HY000)
1 环境: MySQL Server 6.0 命令行工具 2 问题 : 插入中文字符数据出现如下错误: ERROR 1366 (HY000): Incorrect string value: '\ ...
- C++之enum枚举量声明、定义、使用与枚举类详解
C++之enum枚举量声明.定义.使用与枚举类详解 学习一个东西,首先应该指导它能做什么,其次去知道它怎么去做,最后知道为什么去这么做. 知其然知其所以然.不能冒进 ,一步一步的慢慢来.
- 基于代的垃圾回收机制--《CLR via C#》读书笔记
我们知道,垃圾回收在内存无限大的理想情况下是不需要的,正是因为内存存在的瓶颈,我们才需要垃圾回收.在<垃圾回收算法之引用计数算法>和<垃圾回收算法之引用跟踪算法>两篇文章中,我 ...
- POJ3267
从今天开始POJ里的一部分类型的题目就一般不放在一起写了 一个是太丑,格式麻烦,第二个是以后的题目难度都有所增大,因此一道题可能就要写蛮长 尤其是DP这一块,以前一直没好好学习,现在从基础的先开始吧 ...
- 探索sklearn | K均值聚类
1 K均值聚类 K均值聚类是一种非监督机器学习算法,只需要输入样本的特征 ,而无需标记. K均值聚类首先需要随机初始化K个聚类中心,然后遍历每一个样本,将样本归类到最近的一个聚类中,一个聚类中样本特征 ...
- Arcgis安装要素
1. ArcGIS安装过程中需将用户名改为计算机名,该计算机名称时需要新建对话框. 2. ArcGIS Server安装过程中要设置ArcGISWebServices用户的读写权限,即设置ASP.NE ...
- R语言学习 第四篇:函数和流程控制
变量用于临时存储数据,而函数用于操作数据,实现代码的重复使用.在R中,函数只是另一种数据类型的变量,可以被分配,操作,甚至把函数作为参数传递给其他函数.分支控制和循环控制,和通用编程语言的风格很相似, ...
- 前端项目模块化的实践2:使用 Webpack 打包基础设施代码
以下是关于前端项目模块化的实践,包含以下内容: 搭建 NPM 私有仓库管理源码及依赖: 使用 Webpack 打包基础设施代码: 使用 TypeScript 编写可靠类库 使用 TypeScript ...
- ECS centos7 使用外部邮件服务商的465加密端口
ECS centos7 使用外部邮件服务商的465加密端口发送邮件. 1.修改/etc/mail.rc 文件中添加以下的 set smtp="smtps://smtp.163.com:465 ...