zoukankan      html  css  js  c++  java
  • [HNOI2008]水平可见直线

    VI.[HNOI2008]水平可见直线

    一开始以为这是半平面交模板;后来一想,直接求出凸包来就行了。

    我们仍然将所有直线按照斜率从小到大排序。不过这时,我们只需要使用单调栈维护即可。

    具体而言,设栈顶次位、首位直线分别为\(y=k_1x+b_1,y=k_2x+b_2\)

    则其交点位于

    \[\Bigg(\dfrac{b_1-b_2}{k_2-k_1},k_2\Big(\dfrac{b_1-b_2}{k_2-k_1}\Big)+b_2\Bigg) \]

    假设我们现在插入一条新直线\(y=k_0x+b_0\),则弹出队尾,当且仅当

    \[k_2\Big(\dfrac{b_1-b_2}{k_2-k_1}\Big)+b_2\leq k_0\Big(\dfrac{b_1-b_2}{k_2-k_1}\Big)+b_0 \]

    因为其分别是首位、次位直线,所以必有\(k_2-k_1>0\),所以两边直接乘上\(k_2-k_1\),最终得到判别式

    \[k_2(b_1-b_2)+b_2(k_2-k_1)\leq k_0(b_1-b_2)+b_0(k_2-k_1) \]

    直接应用即可。

    时间复杂度\(O(n\log n)\)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    int n,k[50100],b[50100],ord[50100],s[50100],tp;
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++)scanf("%d%d",&k[i],&b[i]),ord[i]=i;
    	sort(ord+1,ord+n+1,[](int u,int v){return k[u]==k[v]?b[u]>b[v]:k[u]<k[v];});
    	s[tp=1]=ord[1];
    	for(int i=2;i<=n;i++){
    		if(k[ord[i]]==k[ord[i-1]])continue;
    		while(tp>=2&&1ll*k[s[tp]]*(b[s[tp-1]]-b[s[tp]])+1ll*b[s[tp]]*(k[s[tp]]-k[s[tp-1]])<=1ll*k[ord[i]]*(b[s[tp-1]]-b[s[tp]])+1ll*b[ord[i]]*(k[s[tp]]-k[s[tp-1]]))tp--;
    		s[++tp]=ord[i];
    	}
    	sort(s+1,s+tp+1);
    	for(int i=1;i<=tp;i++)printf("%d ",s[i]);puts("");
    	return 0;
    } 
    

  • 相关阅读:
    thrift学习
    Spring Bean的生命周期
    无聊的编程题
    jpa双向多对多关联映射
    jpa单向多对多关联映射
    jpa双向一对多关联映射
    jpa单向一对多关联映射
    【计导作业】链表——差集与交集
    【计导作业】链表——成绩统计2
    C语言中访问结构体成员时用‘.’和‘->’的区别
  • 原文地址:https://www.cnblogs.com/Troverld/p/14619293.html
Copyright © 2011-2022 走看看