zoukankan      html  css  js  c++  java
  • Gym

    题意:给点N棵树,前K棵是已经拥有的,现在可以再拥有一棵树,问形成的最大凸包面积。

    思路:先求K棵树的凸包C,然后对于后面的N-K棵树,我们先判断是否在凸包内,如果不在,我们要求两个切线。 这里分类讨论,即可。

    如果点在C的左边,那么两条切线分别一上一下; 如果在下边,两条切线一左一右。 然后去对应区间二分即可。 

    (好像还有双指针的线性做法:求两个凸包,维护两条切线即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=200010;
    struct point{
        ll x,y;
        point(){}
        point(ll xx,ll yy):x(xx),y(yy){}
    };
    bool cmp(point w,point v){
        if(w.x!=v.x) return w.x<v.x;
        return w.y<v.y;
    }
    ll det(point a,point b){ return a.x*b.y-a.y*b.x;}
    ll dot(point a,point b){ return a.x*b.x+a.y*b.y;}
    point operator +(point a,point b){ return point(a.x+b.x,a.y+b.y);}
    point operator -(point a,point b){ return point(a.x-b.x,a.y-b.y);}
    point a[maxn],ch[maxn]; int top,ttop;
    void convexhull(int N)
    {
        for(int i=1;i<=N;i++){
            while(top>1&&det(ch[top]-ch[top-1],a[i]-ch[top-1])<=0) top--;
            ch[++top]=a[i];
        }
        ttop=top;
        for(int i=N-1;i>=1;i--){
            while(top>ttop&&det(ch[top]-ch[top-1],a[i]-ch[top-1])<=0) top--;
            ch[++top]=a[i];
        }
    }
    int get(int L,int R,int i,int w)
    {
        while(L<R){
            int Mid=(L+R)>>1;
            if(det(ch[Mid]-a[i],ch[Mid+1]-a[i])*w>0) R=Mid;
            else L=Mid+1;
        }
        return L;
    }
    int bord(int L,int R,int i,int w)
    {
        while(L<R){
            int Mid=(L+R)>>1;
            if((ch[Mid].x-a[i].x)*w<0) L=Mid+1;
            else R=Mid;
        }
        return L;
    }
    ll ans,sum[maxn],tmp;
    int main()
    {
        int N,K;
        scanf("%d%d",&N,&K);
        rep(i,1,N) scanf("%lld%lld",&a[i].x,&a[i].y);
        sort(a+1,a+K+1,cmp); convexhull(K);
        rep(i,1,top-1) ans+=det(ch[i],ch[i+1]),sum[i+1]=ans;
        rep(i,K+1,N){
            if(a[i].x<ch[1].x){
                int L=get(1,ttop,i,1),R=get(ttop,top,i,-1);
                tmp=sum[R]-sum[L]+det(ch[R],a[i])+det(a[i],ch[L]);
            }
            else if(a[i].x>ch[ttop].x){
                int L=get(1,ttop,i,-1),R=get(ttop,top,i,1);
                tmp=sum[top]-sum[R]+sum[L]+det(ch[L],a[i])+det(a[i],ch[R]);
            }
            else if(det(ch[ttop]-a[1],a[i]-ch[1])>0){//shang
                int Mid=bord(ttop,top,i,-1);
                if(Mid>ttop&&det(ch[Mid]-ch[Mid-1],a[i]-ch[Mid-1])>0) continue;
                int L=Mid>ttop?get(ttop,Mid-1,i,-1):Mid;
                int R=get(Mid,top,i,1);
                tmp=sum[top]-sum[R]+sum[L]+det(ch[L],a[i])+det(a[i],ch[R]);
            }
            else {
                int Mid=bord(1,ttop,i,1);
                if(Mid>1&&det(ch[Mid]-ch[Mid-1],a[i]-ch[Mid-1])>0) continue;
                int L=Mid>1?get(1,Mid-1,i,-1):1;
                int R=get(Mid,ttop,i,1);
                tmp=sum[top]-sum[R]+sum[L]+det(ch[L],a[i])+det(a[i],ch[R]);
            }
            ans=max(ans,tmp);
        }
        printf("%lld.%lld
    ",ans/2,ans%2*5);
        return 0;
    }
    /*
    5 3
    -5 -5
    -5 5
    5 -5
    -4 6
    5 5
    */
  • 相关阅读:
    组合数学练习
    floyd算法新理解
    图论练习
    GDOI2021 day2总结
    P3190 [HNOI2007]神奇游乐园
    P1932 A+B A-B A*B A/B A%B Problem
    P2289 [HNOI2004]邮递员
    P5056 【模板】插头dp
    P4323 [JSOI2016]独特的树叶
    CF1153D Serval and Rooted Tree
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10745667.html
Copyright © 2011-2022 走看看