题解 CF535E 【Tavas and Pashmaks】
蒟蒻的第二篇题解
终于做掉了这一题,趁此题暂无题解,赶紧发了庆祝一下qwq
好了,重点说说此题。
首先可得到这个式子:
\frac{A}{a_{i}}+\frac{B}{b_{i}}=T
其中
接下来是做法:
考虑把 喜欢的一次函数啦。继续把原式变得更通俗
y=-\frac{A}{B}x+\frac{T}{B}
由于点
那么,怎么确定斜率呢?我们可以通过画图发现,是答案的点一定在平面图的左下凸包上,如果明白凸包的思想,
那么问题就很简单了,至于没学过凸包的同学,可以参考yyb的博客或这篇博客(没学凸包还想做此题?),蒟蒻我就不多说了qwq
上代码:
#include<bits/stdc++.h>
#define ll long long
#define ld long double
using namespace std;
inline ll read(){
ll f=1,w=0;char x=0;
while(!(x>='0'&&x<='9'))
{
x=getchar();
if(x=='-') f=-1;
}
while(x>='0'&&x<='9')
{
w=(w<<3)+(w<<1)+(x^48);
x=getchar();
}
return f*w;
}//习惯性的快读
struct people{
ll a,b,id;
}p[300010];
ll n,s[300010],t;
bool v[300010],ans[300010];
bool cmp(people a,people b){
if(a.a==b.a) return a.b>b.b;
return a.a>b.a;
}//凸包排序
ld check(people a,people b){
return (ld)a.a*b.a*(b.b-a.b)/(b.a-a.a)/b.b/a.b;
}//斜率的计算
int main(){
n=read();
for(int i=1;i<=n;i++) p[i].a=read(),p[i].b=read(),p[i].id=i;
sort(p+1,p+n+1,cmp);
s[1]=1,t=1;
ll maxb=p[1].b;
for(int i=2;i<=n;i++)
if(p[i].b<=maxb) v[i]=1;
else maxb=p[i].b;
//去重和排除能一眼看出非答案的点,譬如a和b都比另一个点小
for(int i=2;i<=n;i++)
{
if(v[i]||check(p[i],p[s[t]])>0) continue;//斜率大于0排除(并不知道有没有用
while(t>1&&check(p[i],p[s[t]])<check(p[s[t-1]],p[s[t]]))
t--;
s[++t]=i;
}//单调栈维护的类似于凸包的过程
for(int i=1;i<=t;i++)
{
ans[p[s[i]].id]=1;
for(int j=s[i]+1;j<=n&&p[s[i]].a==p[j].a&&p[s[i]].b==p[j].b;j++)
ans[p[j].id]=1;
}//还原位置相同的点
for(int i=1;i<=n;i++)
if(ans[i]) cout<<i<<" ";
return 0;
}