CF535E Tavas and Pashmaks 单调栈、凸包
题意:有一场比赛,$N$个人参加。每个人有两种参数$a,b$,如果存在正实数$A,B$使得$\frac{A}{a_i} + \frac{B}{b_i}$在$i=x$处取得最大值(可以有多个最大值),则称选手$x$可以夺冠。问共有多少人能够夺冠。$N \leq 2 \times 10^5 , 1 \leq a , b \leq 10^4$
考虑将$(\frac{1}{a_i},\frac{1}{b_i})$看做平面上的点,我们的目标就是在这些点上求目标函数$z=Ax+By$的最小值(线性规划),而对于每一条这样的直线,都一定是与某一个凸包切于一个点或与这个凸包中的某条线重合。可以考虑到这就是若干$(\frac{1}{a_i},\frac{1}{b_i})$的点构成的左下凸包(也就是一个完整凸多边形的左下部分)。将点从大到小排序之后使用单调栈维护凸包即可。
有一个很重要的剪枝:当$a_i \leq a_j , b_i \leq b_j$时,$i$号无需计算
还要注意$a,b$相同的人的计算。
UPD:似乎上面很抽象,画个图解释一下
我们把上面的剪枝做完之后,得到的所有点的坐标横坐标递增,纵坐标递减,且都分布在第一象限。
画在图上就是这样子:
话说Dia画点竟然要用圆形填充,所以点会很大
我们考虑这些点在$z=Ax + By$的目标函数上的最小取值(也就是取一个点带入函数中,使得$z$最小)。
先说结论:不论$A,B$如何取值,最小值一定在下图图形中连上的点上取到。
那么为什么中间那个没连上的点不能取到最优解呢?
我们按照斜率绝对值从大到小观察选点情况,可以知道随着斜率绝对值变小,选择的点的横坐标会不断增加,一个点会成为最优解对应的斜率范围会是一段区间,也就是当斜率越过这个点对应的最优解区间之后,这个点一定不会对最优解产生贡献了。
那么我们考虑在什么情况下最优解会从一个点转移到另一个点。
我们将点从左往右编号。考虑上面两条直线。可以知道当直线的斜率在$[k2,k1]$范围内时,$2$号点会产生最优解,而当$k=k1$时,$4$号点也会产生最优解,而当$k \geq k1$时,最优解就会从$2$号点转移为$4$号点了。
所以我们可以发现,最优解转移时直线的斜率就是这两个点之间的斜率。
接下来我们考虑如何排除非最优解了。
考虑上图中从$2$号点转移到$3$号点与$4$号点的情况。我们发现从$2$号点转移到$3$号点的斜率是$k2$,而从$2$号点转移到$4$号点的斜率是$k1$,且$k1 < k2$。这意味着斜率绝对值从大到小的过程中,$4$号点会比$3$号点先到达最优解转移时的斜率,所以$2$号点的最优解会先转移到$4$号点,而$3$号点无法从$2$号点转移,就是无用的节点了。
所以依据上面的研究,我们可以通过单调栈维护这样子的一个类似凸多边形的结构,模型如下:
①把$1$号点与$2$号点加入栈中
②准备加入一个新的点$i$
③考虑当前栈中是否有无用节点。我们设栈顶下标为$hd$,我们就可以考虑$Stack_{hd}$与$i$从$Stack_{hd - 1}$转移最优解时的斜率(也就是$Stack_{hd}$与$i$和$Stack_{hd - 1}$相连得到的直线的斜率),如果$i$的斜率绝对值大于$Stack_{hd}$的斜率,弹出栈顶,如果栈大小大于$1$,进入③,否则进入④
④加入当前点。如果还有新的点,进入②,否则进入⑤
⑤统计单调栈内的点,对应答案。
#include<bits/stdc++.h> #define ld long double #define eps 1e-10 using namespace std; inline int read(){ ; char c = getchar(); while(!isdigit(c)) c = getchar(); while(isdigit(c)){ a = (a << ) + (a << ) + (c ^ '); c = getchar(); } return a; } ; struct point{ int a , b , ind; }now[MAXN]; int nxt[MAXN] , pre[MAXN] , S[MAXN] , tl; bool can[MAXN]; bool cmp(point a , point b){ if(a.a == b.a) return a.b > b.b; return a.a > b.a; } ld calcK(point a , point b){ return (ld)a.a * b.a * (b.b - a.b) / a.b / b.b / (b.a - a.a); } int main(){ int N = read(); ; i <= N ; i++){ now[i].a = read(); now[i].b = read(); now[i].ind = i; nxt[i] = i + ; pre[i] = i - ; } sort(now + , now + N + , cmp); ].b; //双向链表排除冗余状态 ; i <= N ; i++) if(now[i].b <= maxB){ nxt[pre[i]] = nxt[i]; pre[nxt[i]] = pre[i]; } else maxB = now[i].b; S[] = ; tl = ; //通过斜率维护单调栈(与斜率优化很相似) ] ; i <= N ; i = nxt[i]){ && calcK(now[i] , now[S[tl - ]]) < calcK(now[S[tl - ]] , now[S[tl - ]])) tl--; S[tl++] = i; } ; i < tl ; i++){ can[now[S[i]].ind] = ; //还原原来位置相同的点 ; j <= N && now[S[i]].a == now[j].a && now[S[i]].b == now[j].b ; j++) can[now[j].ind] = ; } ; i <= N ; i++) if(can[i]) printf("%d " , i); ; }
鉴于某人说我直接蒯题解,再来更个精度易爆炸的做法
考虑$\frac{A}{a_i} + \frac{B}{b_i}$,除掉$B$可以得到一个自变量为$\frac{A}{B}$的线,将这些线用斜率优化的方式加入就可以了,实质也是维护一个凸包。但是这种做法对于精度要求很高,似乎要把斜率与截距同乘$10^9$才能保证精度(或者使用一般式)
CF535E Tavas and Pashmaks 单调栈、凸包的更多相关文章
- BZOJ_1007_ [HNOI2008]_水平可见直线_(单调栈+凸包)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1007 给出一些直线,沿着y轴从上往下看,能看到多少条直线. 分析 由于直线相交,会遮挡住一些直 ...
- Building(单调栈+凸包)
Problem Description Once upon a time Matt went to a small town. The town was so small and narrow tha ...
- CF535E Tavas and Pashmaks
今天Fakehu考的T1. 大致意思就是有n个人每个人有两个速度\(v_1,v_2\),比赛有两个路程\(A,B\),最后时间是\(A/v_1+B/v_2\).求每个人是否可能成为冠军中的一个. 显然 ...
- [CSP-S模拟测试]:导弹袭击(数学+凸包+单调栈)
题目背景 $Guess$准备向敌军阵地发起进攻了!$Guess$的武器是自动制导导弹.然而在机房是不允许游戏的,所以班长$XZY$对游戏界面进行了降维打击,结果... 题目描述 众所周知,环境因素对导 ...
- 【Cf #299 C】Tavas and Pashmaks(单调栈,凸性)
一个经典的二维数点模型,如果某个人 $ x $ 两个速度都比另一个人 $ y $ 大,显然 $y$ 是不可能成为winner的. 但这里只考虑两个人$x$,$y$在两个属性各有千秋的时候,一定存在正整 ...
- 【bzoj5089】最大连续子段和 分块+单调栈维护凸包
题目描述 给出一个长度为 n 的序列,要求支持如下两种操作: A l r x :将 [l,r] 区间内的所有数加上 x : Q l r : 询问 [l,r] 区间的最大连续子段和. 其中,一 ...
- [CSP-S模拟测试]:A(单调栈维护凸包+二分答案)
题目传送门(内部题150) 输入格式 第一行两个整数$N,Q$. 接下来的$N$行,每行两个整数$a_i,b_i$. 接下来的$Q$行,每行一个整数$x$. 输出格式 对于每个询问,输出一行一个整数表 ...
- Function:凸包,单调栈,题意转化,单峰函数三分,离线处理
很难啊啊啊!!! bzoj5380原题,应该可以粘题面. 问题转换: 有一个n列1e9行的矩阵,每一列上都写着相同的数字Ai. 你从位置(x,y)出发每一步可以向左上方或左方走一步,最后走到第一行. ...
- Lost My Music:倍增实现可持久化单调栈维护凸包
题目就是求树上每个节点的所有祖先中(ci-cj)/(dj-di)的最小值. 那么就是(ci-cj)/(di-dj)的最大值了. 对于每一个点,它的(ci,di)都是二维坐标系里的一个点 要求的就是祖先 ...
随机推荐
- docker第一章:docker核心概念及centos6下安装
Docker三大核心概念 镜像 容器 仓库 镜像 docker镜像类似于虚拟机镜像,可以将它理解为一个面向Docker引擎的只读模板,包含了文件系统. 容器 1.容器是从镜像创建的应用运行实例,容器和 ...
- Salesforce的公式和验证规则
公式 在Salesforce中,有些功能不需要从数据库中直接读取的数据,而是基于这些数据之间的关系来做出判断.这种情况下就要用到"公式"功能. 公式的概念和Excel中的公式类似, ...
- Python 利用Python操作excel表格之xlwt介绍
利用Python操作excel表格之xlwt介绍 by:授客 QQ:1033553122 直接上代码 案例1 #!/usr/bin/env python # -*- coding:utf-8 ...
- 浅谈Java多线程同步机制之同步块(方法)——synchronized
在多线程访问的时候,同一时刻只能有一个线程能够用 synchronized 修饰的方法或者代码块,解决了资源共享.下面代码示意三个窗口购5张火车票: package com.jikexueyuan.t ...
- recovery 差分升级包制作超时
我们在对android系统升级的时候,可以减少升级包的大小,只升级差异部分,也就是差分包升级,相关的描述可以参考:http://blog.csdn.net/csdn66_2016/article/de ...
- javascript避免dom事件重复触发
/** * 为指定控件添加限制性事件, 该事件在触发之后, 会被移除, 并在指定的时间间隔后, 重新绑定, 适用于避免控件事件被误操作重复触发的场景 * @param {String} domID 要 ...
- Xamarin是无懈可击还是鸡肋?浅谈对Xamarin的学习
微软宣布跨平台已经有几个年头,当C#代码可以在其他平台运行时,我相信对于每个热爱.net的程序猿还是十分欣慰的,最近工作需要在一直研究和学习.net的跨平台开发Xamarin,网上对其优点总结也是一大 ...
- PHP实现一个简陋的注册登录页面
PHP实现一个简陋的注册登录页面 今天来水一篇没有**用的 /滑稽脸,代码简陋臃肿考虑不全,各位大佬轻喷,还望不吝赐教. 首先考虑了一下需要至少四个页面:register.html.register. ...
- 一道题引发的self和super
这个是那道题目,让写出输出的结果: 刚看到这一道题目的时候我的第一反应就是输出Son Father.但是输出的结果是Son Son. 下面是解析: 我首先建立了两个类,一个Fathe ...
- js 提交表单添加csrf
function post(path, shipmentMap, method) { method = method || "post"; // Set method to pos ...