5163: 第k大斜率
Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 15 Solved: 4
[Submit][Status][Discuss]
Description
在平面直角座標系上,有n個不一樣的點。任意兩個不一樣的點肯定了一條直線。請求出全部斜率存在的直線按斜率從
大到小排序後,第k條直線的斜率爲多少。爲了不精度偏差,請輸出斜率向下取整後的結果。(例如:[1.5]=1,
[-1.5]=-2)
Input
第一行,包含兩個正整數n和k。
接下來n行,每行包含兩個整數xi,yi,表示每一個點的橫縱座標。
1 ≤ n≤ 100000 , k ≤ n , |xi|, |yi| ≤ 10^8
Output
輸出一行,包含一個整數,表示第k小的斜率向下取整的結果。php
Sample Input
4 1
-1 -1
2 1
3 3
1 4
-1 -1
2 1
3 3
1 4
Sample Output
2
估計正解對於你們來講都很簡單。。。可是這題的題面太坑了。
首先不要輕易相信上述的題面,讓我先來說講個人作題過程。。。。。
1.x座標相同的是否是算斜率無窮大啊????一開始我這麼想,後來發現x座標的斜率不算以後能多撐1s多再WA,這說明x座標相同的不能算。。。
這個仍是最不坑啊,,,,
2.大家發沒發現題目的OUTPUT裏寫的是第k小,可是經過觀察樣例和題目描述發現實際上是第k大。。。
這個也還好,畢竟寫反了能夠看樣例看出來。。。可是最後這個。。。
3.題目裏說k<=n,我一開始還真信了hhhh,後來一直WA一直WA終於想到了n個點最多有n*(n-1)/2條能夠計算斜率的直線,因此k開成long long仍是好一點。。。
(而後開成long long就A了hhhh,我TM要打死出題人這題面真是沒誰了,估計還要誤導好多人hhhh)
#include<bits/stdc++.h> #define ll long long #define maxn 100005 using namespace std; int l,r,mid,ans; const int inf=1000000000; int px[maxn],ky; struct node{ int x,y; ll tmp; bool operator <(const node& u)const{ return tmp==u.tmp?x<u.x:tmp<u.tmp; } }a[maxn]; int n,m,f[maxn]; ll k; inline int query(int x){ int an=0; for(;x;x-=x&-x) an+=f[x]; return an; } inline void update(int x,int y){ for(;x<=ky;x+=x&-x) f[x]+=y; } inline ll calc(){ ll an=0; memset(f,0,sizeof(f)); for(int i=1;i<=n;i++) a[i].tmp=(ll)a[i].y-mid*(ll)px[a[i].x]; sort(a+1,a+n+1); for(int i=1;i<=n;i++){ an+=(ll)query(a[i].x-1); update(a[i].x,1); } return an; } int main(){ scanf("%d%lld",&n,&k); for(int i=1;i<=n;i++){ scanf("%d%d",&a[i].x,&a[i].y); px[i]=a[i].x; } sort(px+1,px+n+1); ky=unique(px+1,px+n+1)-px-1; for(int i=1;i<=n;i++) a[i].x=lower_bound(px+1,px+ky+1,a[i].x)-px; l=-inf,r=inf; while(l<=r){ mid=l+r>>1; if(calc()>=k) ans=mid,l=mid+1; else r=mid-1; } printf("%d\n",ans); return 0; }