一个经典的二维数点模型,如果某个人 $ x $ 两个速度都比另一个人 $ y $ 大,显然 $y$ 是不可能成为winner的。

但这里只考虑两个人$x$,$y$在两个属性各有千秋的时候,一定存在正整数$S$,$R$使得$x$,$y$都有可能成为winner。

这时考虑单调栈中顶端的两个人$a$和$b$,以及此时准备加入的人$c$,很明显当两两无法比较时,可能存在如下情况:

  1. 当$S$与$R$的比值小于一定值时,$a$总能胜$b$。
  2. 当$S$与$R$的比值大于一定值时,$c$总能胜$b$。

可以看到,当前者的阀值大于后者的阀值时,就不存在任何一组$S$和$R$,能使$b$成为winner了。(注:这里已经将人按照$s$值排了序)

前者的不等式大概长这样(当$a$能胜$b$):

$ \frac{ s_{a} \, s_{b} \, ( r_{a} - r_{b} ) }{ r_{a} \, r_{b} \, ( s_{b} - s_{a} ) } > \frac{ S }{ R } $

后者的不等式大概长这样(当$c$能胜$b$):

$ \frac{ s_{c} \, s_{b} \, ( r_{b} - r_{c} ) }{ r_{c} \, r_{b} \, ( s_{c} - s_{b} ) } < \frac{ S }{ R } $

将式子化简后就能判断$b$有没有win的可能性了。

这里简单证明为什么单调栈做可以不遗漏地剔除所有不合法的人:

  1. 在单调栈维护的过程中,保证了占中连续三个人之间是合法的。
  2. 也就是对于任意的 $x_{i }$,$x_{i+1}$,$x_{i+2}$,假设$x_{i}$能胜$x_{i+1}$的阀值是$v_{i}$,都有$v_{i} < v_{i+1}$,即合法的。
  3. 现在要证明对于在栈中的任意的$x_{i}$,$x_{j}$,$x_{k}$,其中$i < j < k$,都不能使$x_{j}$被剔除。

考虑另一种思路,可以将以上棘手的证明转化:

将每一个人的属性以$(\frac{1}{s_{i}}, \frac{1}{r_{i}})$的形式投射到坐标系上。答案$t = \frac{S}{s_{i}} + \frac{R}{r_{i}} = (S, R) \cdot (\frac{1}{s_{i}} + \frac{1}{r_{i}})$。

即在$(S,R)$方向上的投影。

对于任意一个$(S,R)$,在它上投影相等的点在一条垂直于它的直线上,该直线越靠近原点,投影长度越小。

枚举的任意一个$(S,R)$就相当于枚举了一条这直线,最先出现在直线平行线上的点就是winner。

显然,这个点在下凸壳上。并且可以得到,对于下凸壳上的每一个点都存在一组$(S,R)$使得其为winner。

而我们单调栈所做的就相当于自右下而左上地求出这样一个下凸壳。事实证明,两者的表达式是完全相同的。

$ \bigodot $ 技巧&套路:

  • 单调栈的应用,单调栈剔除的变式。
 #include <cstdio>
#include <set>
#include <algorithm> typedef long long LL;
const int N = ; struct No {
int x, y, id;
inline friend bool operator < (No a, No b) {
return (a.x == b.x)? (a.y < b.y) : (a.x < b.x);
}
} p[N]; int n, sta[N], top;
std::set<No> S; inline int Check(No a, No b, No c) {
return (LL) a.x * (a.y - b.y) * c.y * (c.x - b.x) > (LL) c.x * (b.y - c.y) * a.y * (b.x - a.x);
} int main() {
scanf("%d", &n);
for (int i = ; i <= n; ++i) {
scanf("%d%d", &p[i].x, &p[i].y);
p[i].id = i;
}
std::sort(p + , p + + n); for (int i = ; i <= n; ++i) {
while (top >= && p[sta[top]].y <= p[i].y) --top;
while (top >= && Check(p[sta[top - ]], p[sta[top]], p[i])) --top;
sta[++top] = i;
}
for (int i = ; i <= top; ++i) {
S.insert(p[sta[i]]);
}
top = ;
for (int i = ; i <= n; ++i) {
if (S.count(p[i])) sta[++top] = p[i].id;
}
std::sort(sta + , sta + + top);
for (int i = ; i <= top; ++i) {
printf("%d ", sta[i]);
} return ;
}

【Cf #299 C】Tavas and Pashmaks(单调栈,凸性)的更多相关文章

  1. CF535E Tavas and Pashmaks 单调栈、凸包

    传送门 题意:有一场比赛,$N$个人参加.每个人有两种参数$a,b$,如果存在正实数$A,B$使得$\frac{A}{a_i} + \frac{B}{b_i}$在$i=x$处取得最大值(可以有多个最大 ...

  2. CF 602 D. Lipshitz Sequence 数学 + 单调栈 + 优化

    http://codeforces.com/contest/602/problem/D 这题需要注意到的是,对于三个点(x1, y1)和(x2, y2)和(x3, y3).如果要算出区间[1, 3]的 ...

  3. Codeforces Round #299 (Div. 1)C. Tavas and Pashmaks (凸壳)

    C. Tavas and Pashmaks   Tavas is a cheerleader in the new sports competition named "Pashmaks&qu ...

  4. CF Mike and Feet (求连续区间内长度为i的最小值)单调栈

    Mike and Feet time limit per test 1 second memory limit per test 256 megabytes input standard input ...

  5. [CSP-S模拟测试]:导弹袭击(数学+凸包+单调栈)

    题目背景 $Guess$准备向敌军阵地发起进攻了!$Guess$的武器是自动制导导弹.然而在机房是不允许游戏的,所以班长$XZY$对游戏界面进行了降维打击,结果... 题目描述 众所周知,环境因素对导 ...

  6. 【单调栈】最长不上升子序列变式,洛谷 P2757 导弹的召唤

    题目背景 易琢然今天玩使命召唤,被敌军用空对地导弹轰炸,很不爽:众所周知,易琢然很不老实,他开了外挂: 外挂第一次可以打掉任意高度的导弹,之后每一次都不能打掉大于上一次高度的导弹: 但易琢然水平太差, ...

  7. BZOJ1012: [JSOI2008]最大数maxnumber [线段树 | 单调栈+二分]

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 8748  Solved: 3835[Submi ...

  8. BZOJ 4453: cys就是要拿英魂![后缀数组 ST表 单调栈类似物]

    4453: cys就是要拿英魂! Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 90  Solved: 46[Submit][Status][Discu ...

  9. BZOJ 3238: [Ahoi2013]差异 [后缀数组 单调栈]

    3238: [Ahoi2013]差异 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2326  Solved: 1054[Submit][Status ...

随机推荐

  1. Go语言2

    Go语言特点: 类型检查:编译时 运行环境:编译成机器代码直接运行 编程范式:面向接口,函数式编程,并发编程 Go并发编程 采用CSP(Communication Sequenication Proc ...

  2. 【snaptype nexus】搭建maven私服仓库

    搭建本地开发私库,旨在解决本地开始受限于网络环境的问题:具体的搭建步骤主要包含以下几个步骤: 1.私服服务器使用的是ubuntu,首先下载安装包(版本号:2.12),下载地址:http://www.s ...

  3. IDEA主题设置

    主题下载: Color Themes(个人倾向该网站,而不是http://www.riaway.com/) 主题设置: 打开IDEA,按下Ctrl+Alt+S,选择Editor-->Color ...

  4. NO.3_1:自学python之路------番外:第三方库安装、numpy

    引言 Python因为pip的存在,使得第三方库的发布和获取都比较方便.并且Python对跨平台的支持,使得其相较于C++,Java更加方便使用.在本文中,将会介绍在Windows中安装第三方库的方法 ...

  5. Redux 入门教程(一):基本用法

    转自http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html(仅供个人学习使用) 首先明确一点, ...

  6. 从汉诺塔游戏理解python递归函数

    汉诺塔游戏规则: 有三根相邻的柱子,标号为A,B,C,A柱子上从下到上按金字塔状叠放着n个不同大小的圆盘,现在把所有盘子一个一个移动到柱子B上,并且每次移动同一根柱子上都不能出现大盘子在小盘子上方 图 ...

  7. Java调用XML的方法:DocumentBuilderFactory

    (1)首先得到:得到 DOM 解析器的工厂实例 DocumentBuilderFactory domfac=DocumentBuilderFactory.newInstance(); (2)然后从 D ...

  8. javaweb 安全传输签名机制

    java web传输中的安全签名说明: 对请求中的数据 Key对进行签名,最终生成一个签名字符串,标记为sign:"djflw8wejwl9w0ejwlush8fw9ew9",位数 ...

  9. webpack入门指南-step04

    一.建立项目 建一个文件夹,然后新建一个package.json的文件在项目根目录下 如果你使用git管理你的这个项目的话,建议你新建一个.gitignore文件,不要让git提交一些node依赖的模 ...

  10. VS code MacOS 环境搭建

    环境:MacBook Pro 参考博客 为了动手开发AI代码,我需要安装一个VS code. 开始我以为是安装visual studio呢.我装过visual studio2017. VS code是 ...