• 【坐标变换】【二维偏序】【线段树】Gym


    题意:第一象限有n个点,你从x正半轴任选一个位置出发,vy恒定,vx可以任意变化,不过只能在-vy/r到vy/r之间变化,问你最多能经过多少个点。

    暴力dp是n^2,不可取。

    注意到,一个点,所能到达它的点,是它后面一个张角内的所有点。这个张角很容易算出。

    于是可以将这些点全部映射到一个新的坐标系内,使得这个坐标系内每个点左下方的点都是能到达它的点。(没必要真的算出那些真的变换后的坐标,可以以到那个虚拟张角的两条边的距离作为坐标,这样虽然扭曲了一点,但不影响答案。)

    于是转化成了二维偏序问题,可以用一维排序+一维线段树维护左下方的最大值来解决。

    注意是实数点,离散化的时候要处理好误差。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const double eps=0.0000001;
    struct Point{
        double x,y;
        Point(const double &x,const double &y){
            this->x=x;
            this->y=y;
        }
        Point(){}
        void read(){
            scanf("%lf%lf",&x,&y);
        }
        double length(){
            return sqrt(x*x+y*y);
        }
    }a[100005];
    typedef Point Vector;
    Vector operator - (const Point &a,const Point &b){
        return Vector(a.x-b.x,a.y-b.y);
    }
    double Cross(const Vector &a,const Vector &b){
        return a.x*b.y-a.y*b.x;
    }
    double DisToLine(Point P,Point A,Point B)
    {
    	Vector v1=B-A,v2=P-A;
    	return fabs(Cross(v1,v2))/v1.length();
    }
    int n,r,w,h;
    pair<double,int> b[100005];
    struct data{
        double v;
        int p;
        data(const double &v,const int &p){
            this->v=v;
            this->p=p;
        }
        data(){}
    }t[100005];
    bool cmp(const data &a,const data &b){
        return a.v<b.v;
    }
    bool cm2(const pair<double,int> &a,const pair<double,int> &b){
        return a.second<b.second;
    }
    int ans;
    int maxv[100005<<2];
    void update(int p,int v,int rt,int l,int r){
        if(l==r){
            maxv[rt]=v;
            return;
        }
        int m=(l+r>>1);
        if(p<=m){
            update(p,v,rt<<1,l,m);
        }
        else{
            update(p,v,rt<<1|1,m+1,r);
        }
        maxv[rt]=max(maxv[rt<<1],maxv[rt<<1|1]);
    }
    int query(int ql,int qr,int rt,int l,int r){
        if(ql<=l && r<=qr){
            return maxv[rt];
        }
        int m=(l+r>>1),res=0;
        if(ql<=m){
            res=max(res,query(ql,qr,rt<<1,l,m));
        }
        if(m<qr){
            res=max(res,query(ql,qr,rt<<1|1,m+1,r));
        }
        return res;
    }
    int main(){
        //freopen("g.in","r",stdin);
        scanf("%d%d%d%d",&n,&r,&w,&h);
        Point p=Point((double)w*0.5,-(double)w*(double)r*0.5);
        Point q=Point((double)w,0.0);
        Point yd=Point(0.0,0.0);
        for(int i=1;i<=n;++i){
            a[i].read();
            double d1=DisToLine(a[i],p,q);
            double d2=DisToLine(a[i],p,yd);
            a[i]=Point(d1,d2);
            b[i].first=d1;
            t[i].v=d2;
            t[i].p=i;
        }
        sort(t+1,t+n+1,cmp);
        int zy=0;
        b[t[1].p].second=++zy;
        for(int i=2;i<=n;++i){
            if(fabs(t[i].v-t[i-1].v)>eps){
                ++zy;
            }
            b[t[i].p].second=zy;
        }
        int sta;
        sort(b+1,b+n+1);
        for(int i=1;i<=n;++i){
            if(i==1 || fabs(b[i].first-b[i-1].first)>eps){
                sta=i;
            }
            if(i==n || fabs(b[i].first-b[i+1].first)>eps){
                sort(b+sta,b+i+1,cm2);
                for(int j=sta;j<=i;++j){
                    int x=query(1,b[j].second,1,1,zy);
                    ans=max(ans,x+1);
                    update(b[j].second,x+1,1,1,zy);
                }
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
  • 相关阅读:
    [设计] 判断LOGO好坏的12条参考标准
    [3D] (开源)1997年世界编程大赛第一名作品
    [CSS3] 哆啦A梦告诉你目前各家浏览器对 CSS3 的支持状况(含源文件)
    [游戏] 游戏开发中常用的设计模式
    [D3D] DX10 D3D10阴影技术演示Demo
    [D3D(C#)] 创建设备
    [JS] 全世界最短的IE判定
    [游戏] 游戏中的资源管理资源高速缓存
    [游戏] 网络游戏:为什么失败
    [VC] (开源)游戏源代码列表
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7756158.html
Copyright © 2020-2023  润新知