• Luogu P4479 [BJWC2018]第k大斜率


    一道清真简单的好写的题

    Luogu P4479


    题意

    求点集两两连出的直线中斜率第$ k$大的直线


    $ Solution$

    二分答案,设$x_j geq x_i$

    若点$ (x_i,y_i)$和点$(x_j,y_j)$构成的斜率大于二分的答案$ k$则有

    $ frac{y_j-y_i}{x_j-x_i} geq k$

    $y_j-k·x_j geq y_i-k·x_i$

    转化成二维偏序

    树状数组/归并排序维护即可

    注意特判各种边界问题

    时间复杂度$ O(n log^2 n)$


    $ my code$

    #include<ctime>
    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    #define rt register int
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x = 0; char zf = 1; char ch = getchar();
        while (ch != '-' && !isdigit(ch)) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    void write(ll y){if(y<0)putchar('-'),y=-y;if(y>9)write(y/10);putchar(y%10+48);}
    void writeln(const ll y){write(y);putchar('
    ');}
    ll n,m;
    struct node{
        int x,y;
        bool operator <(const node s)const{
            if(x==s.x)return y>s.y;
            return x<s.x;
        }
    }a[100010];
    ll q[100010],zs[100010],ans;
    ll calc(int L,int R){
        if(L==R)return 0;
        if(ans>=m)return ans;
        const int mid=L+R>>1;
        calc(L,mid);calc(mid+1,R);if(ans>=m)return ans;
        for(rt i=mid+1,j=L;i<=R;i++){
            while(j<=mid&&q[j]<=q[i])j++;
            ans+=j-L;
        }
        int tot1=L,tot2=mid+1,pl=L;
        while(tot1<=mid||tot2<=R){
            if(tot1>mid||(q[tot1]>q[tot2]&&tot2<=R))zs[pl++]=q[tot2++];
            else zs[pl++]=q[tot1++];
        }
        for(rt i=L;i<=R;i++)q[i]=zs[i];
        return ans;
    }
    bool check(int x){
        ans=0;
        for(rt i=1;i<=n;i++)q[i]=(ll)a[i].y-(ll)x*a[i].x;
        return (calc(1,n)>=m);
    }
    int main(){
        n=read();m=read();
        for(rt i=1;i<=n;i++)a[i].x=read(),a[i].y=read();
        sort(a+1,a+n+1);
        int L=-200000000,R=200000000;
        while(L<=R){
            const int mid=L+R>>1;
            if(check(mid))L=mid+1;
            else R=mid-1;
        }
        write(R);
        return 0;
    }
  • 相关阅读:
    笔记本搜不到无线网络连接[转]
    局域网IP冲突
    CFree 修改/添加编译配置环境(Build Configuration)
    字母索引网页
    NAOChoregraphe"单机使用许可证使用了多次"问题解决方案
    redis源码笔记-dict.c
    redis源码笔记-sds
    redis源码笔记-testhelp
    redis源码笔记-endian
    redis源码笔记-dict.h
  • 原文地址:https://www.cnblogs.com/DreamlessDreams/p/10083396.html
Copyright © 2020-2023  润新知