zoukankan      html  css  js  c++  java
  • 【BZOJ 1038】[ZJOI2008]瞭望塔

    【题目链接】:http://www.lydsy.com/JudgeOnline/problem.php?id=1038

    【题意】

    【题解】

    可以看到所有村子的瞭望塔所在的位置只会是在相邻两个村子所代表的点连成的线的半平面交内;
    它求的是相对高度;
    有个结论是:
    最小相对高度差的点,
    1.在半平面交的直线的交点处
    2.在村子往上的投影处;
    平面交用单调队列搞;
    搞之前需要先将直线按斜率升序排;
    然后就可以想象一下斜率都是0..90°的情形,然后写一些就好;
    具体实现看代码;

    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define rei(x) scanf("%d",&x)
    #define rel(x) scanf("%lld",&x)
    #define ref(x) scanf("%lf",&x)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int N = 1000;
    
    struct point
    {
        double x,y;
    }points[N];
    
    struct line
    {
        point a,b;
        double k,c;
        void get()
        {
            k = (a.y-b.y)/(a.x-b.x);
            c = a.y-k*a.x;
        }
    }lines[N],sta[N];
    
    int n,top = 0;
    double ans = 1e12;
    
    void in()
    {
        rei(n);
        rep1(i,1,n)
            ref(points[i].x);
        rep1(i,1,n)
            ref(points[i].y);
    }
    
    bool cmp1(line a,line b)//把线段按照斜率升序排
    {
        return a.k < b.k;
    }
    
    point getintersec(line a,line b)//求两条直线的交点
    {
        point t;
        t.x = (a.c-b.c)/(b.k-a.k);
        t.y = t.x*a.k+a.c;
        return t;
    }
    
    void Insert(line t)//插入一条新的平面
    //因为都会是往上的,所以处理起来会简单一点吧
    {
        while (top>=2)
        {
            if (getintersec(sta[top-1],sta[top]).x>getintersec(sta[top],t).x) top--;
            else
                break;
        }
        sta[++top] = t;
    }
    
    void halfpaneintersec()//搞平面交
    {
        rep1(i,1,n-1)
            Insert(lines[i]);
    }
    
    void pre()
    {
        rep1(i,1,n-1)
            lines[i].a = points[i],lines[i].b = points[i+1],lines[i].get();
        sort(lines+1,lines+1+(n-1),cmp1);
        halfpaneintersec();
    }
    
    double maxh(double x)//村子的投影往上的交点的纵坐标
    {
        double t = 0;
        rep1(i,1,top)
        {
            double y = sta[i].k*x+sta[i].c;
            t = max(t,y);
        }
        return t;
    }
    
    double jdy(double x)//平面交的直线的交点的横坐标往下的投影的交点纵坐标
    {
        rep1(i,2,n)
        {
            if (points[i].x>=x)
                return points[i].y-(points[i].y-points[i-1].y)*(points[i].x-x)/(points[i].x-points[i-1].x);
        }
        return 0;
    }
    
    void get_ans()
    {
        rep1(i,1,n)
            ans = min(ans,maxh(points[i].x)-points[i].y);
        rep1(i,1,top-1)
        {
            point t = getintersec(sta[i],sta[i+1]);
            ans = min(ans,t.y-jdy(t.x));
        }
    }
    
    void o()
    {
        printf("%.3f
    ",ans);
    }
    
    int main()
    {
        //freopen("F:\rush.txt","r",stdin);
        in();
        pre();
        get_ans();
        o();
        //printf("
    %.2lf sec 
    ", (double)clock() / CLOCKS_PER_SEC);
        return 0;
    }
    
  • 相关阅读:
    Failed to create the Java Virtual Machine
    图文解析进程与线程区别
    HTTP协议详解
    打开某网站无法访问出现空白页可能的原因
    子网划分举例
    上传验证绕过全解析
    Linux命令之远程登录与执行远程主机命令
    information_schema Introduction
    python多进程之multiprocessing
    python多线程之Threading
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626524.html
Copyright © 2011-2022 走看看