码迷,mamicode.com
首页 > 其他好文 > 详细

Mountainous landscape

时间:2018-08-29 14:54:05      阅读:203      评论:0      收藏:0      [点我收藏+]

标签:cst   vector   const   凸包   info   处理   can   直接   ==   

Portal --> broken qwq

Solution

?  所以我不是很懂为什么我场上想到了凸包的解法但是。。老想着。。要整体处理==有毒

?  一开始。。自己进入了一个误区就是老想着要求交点

??  但是很显然求交点你就凉了,所以我们要转化问题技术分享图片

??  我们把橙黄色的那条线画出来,然后就发现。。其实我们是可以很方便地判断一段线段(\(P_3P_4\)),在某一个区间里面有没有解,具体的话就是。。我们维护这个区间的上凸包,然后判断一下这条线跟是否与这个上凸包相交就好了

??  那然后就直接。。线段树维护每个区间的上凸包。。然后直接在线段树上查答案就ok了然后记得优秀左儿子。。时间复杂度\(O(nlog^2n)\)

?  

?  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int N=1e5+10,SEG=N*4;
const double eps=1e-6;
struct Dot{
    double x,y;
    Dot(){}
    Dot(double _x,double _y){x=_x; y=_y;}
}a[N];
bool slope_dec(int x,int y,int i){return (a[x].y-a[y].y)*(a[y].x-a[i].x)>(a[y].y-a[i].y)*(a[x].x-a[y].x);}
void line(int x,int y,double &k,double &b){
    k=(a[x].y-a[y].y)/(a[x].x-a[y].x);
    b=a[x].y-k*a[x].x;
}
bool k_bigger(int x,int y,double k){
    if (a[y].x>a[x].x) swap(x,y);
    return (a[x].y-a[y].y)>k*(a[x].x-a[y].x);
}
int n,ans;
namespace Seg{/*{{{*/
    int ch[SEG][2],top[SEG];
    vector<int> rec[SEG];
    int n,tot;
    double k,b;
    void _build(int x,int l,int r){
        rec[x].resize(r-l+3); top[x]=0;
        for (int i=l;i<=r+1;++i){
            while (top[x]>1&&!slope_dec(rec[x][top[x]-1],rec[x][top[x]],i)) --top[x];
            rec[x][++top[x]]=i;
        }
        rec[x].resize(top[x]+1);
        if (l==r) return;
        int mid=l+r>>1;
        ch[x][0]=++tot; _build(ch[x][0],l,mid);
        ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
    }
    void build(int _n){n=_n; tot=1; _build(1,1,n);}
    int check(int x){
        int l=1,r=top[x]-1,mid,tmp1,tmp2,ans=r;
        while (l<=r){
            mid=l+r>>1;
            tmp1=rec[x][mid];
            tmp2=rec[x][mid+1];
            if (k_bigger(tmp1,tmp2,k)) 
                ans=mid,l=mid+1;
            else r=mid-1;
        }
        tmp1=rec[x][ans+1];
        if (k*a[tmp1].x+b+eps<=a[tmp1].y) return tmp1-1;
        else return 0;
    }
    int _query(int x,int l,int r,int lx,int rx){
        int mid=lx+rx>>1,tmp;
        if (l<=lx&&rx<=r){
            if (lx==rx) return check(x);
            if (!check(x)) return 0;
            if (check(ch[x][0]))
                return _query(ch[x][0],l,r,lx,mid);
            return _query(ch[x][1],l,r,mid+1,rx);
        }
        if (r<=mid)
            return _query(ch[x][0],l,r,lx,mid);
        else if (l>mid)
            return _query(ch[x][1],l,r,mid+1,rx);
        else{
            tmp=_query(ch[x][0],l,mid,lx,mid);
            if (tmp) return tmp;
            return _query(ch[x][1],mid+1,r,mid+1,rx);
        }
    }
    int query(int l,int r,double k1,double b1){k=k1; b=b1;return _query(1,l,r,1,n);}
    void _debug(int x,int lx,int rx){
        printf("#%d %d: ",lx,rx);
        for (int i=1;i<=top[x];++i) printf("%d ",rec[x][i]);
        printf("\n");
        if (lx==rx)  return;
        int mid=lx+rx>>1;
        _debug(ch[x][0],lx,mid);
        _debug(ch[x][1],mid+1,rx);
    }
    void debug(){_debug(1,1,n);}
}/*}}}*/

int main(){
#ifndef ONLINE_JUDGE
    freopen("a.in","r",stdin);
#endif
    double k,b;
    scanf("%d",&n);
    for (int i=1;i<=n;++i)
        scanf("%lf%lf\n",&a[i].x,&a[i].y);
    Seg::build(n-1);
    //Seg::debug();
    for (int i=1;i<n;++i){
        ans=0;
        if (i<=n-2){
            line(i,i+1,k,b);
            ans=Seg::query(i+1,n-1,k,b);
        }
        printf("%d ",ans);
        //Seg::debug();printf("\n");
    }
}

Mountainous landscape

标签:cst   vector   const   凸包   info   处理   can   直接   ==   

原文地址:https://www.cnblogs.com/yoyoball/p/9552444.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!