题目链接:[BJWC2018]第k大斜率
显然可以二分答案,然后找大于当前答案的斜率个数。
怎么判断呢?
假设当前斜率为k,则:(yi-yj) / (xi-xj) > k
假设xi>xj 则:
yi-k*xi>yj-k*xj
只要满足这个条件即可,其实我们可以发现,就是一个二维偏序。
AC代码:
#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+10;
int n,k,res,d[N],l=-2e8,r=2e8;
struct node{int x,y;}t[N];
vector<int> v;
int cmp(node a,node b){return a.x==b.x?a.y>b.y:a.x<b.x;}
inline void insert(int x){for(;x<=v.size();x+=x&(-x)) d[x]++;}
inline int ask(int x){int s=0; for(;x;x-=x&(-x)) s+=d[x]; return s;}
inline int sum(int l,int r){return ask(r)-ask(l-1);}
inline int check(int mid){
v.clear(); res=0; memset(d,0,sizeof d);
for(int i=1;i<=n;i++) v.push_back(t[i].y-mid*t[i].x);
sort(v.begin(),v.end()),v.erase(unique(v.begin(),v.end()),v.end());
for(int i=1,val;i<=n;i++){
val=lower_bound(v.begin(),v.end(),t[i].y-mid*t[i].x)-v.begin()+1;
res+=ask(val),insert(val);
}
return res>=k;
}
signed main(){
cin>>n>>k;
for(int i=1;i<=n;i++) scanf("%lld %lld",&t[i].x,&t[i].y);
sort(t+1,t+1+n,cmp);
while(l<r){
int mid=l+r+1>>1;
if(check(mid)) l=mid;
else r=mid-1;
}
printf("%lld\n",l);
return 0;
}