• bzoj2402 陶陶的难题II


    这个是题目描述:

    题解:

    啊啊啊啊啊……

    垃圾分数规划。

    垃圾树链剖分。

    垃圾斜率优化。

    垃圾darkbzoj

    这里才是题解:

    我们设那个分数的值=k,那么有

    $(yi-k*xi)+(qj-k*pj)=0$

    我们要做的是让k最大。

    那么很明显开两颗线段树,每个节点存一个凸包。

    鉴于我们要让b值最大,我们要维护一个上凸包。

    然后就是三分凸包+树剖。

    代码:

    #include<cmath>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define N 30050
    #define db double
    int n,hed[N],cnt,m;
    const db inf = 1e10;
    const db eps = 1e-6;
    struct Pnt
    {
        db x,y;
    }p1[N],p2[N];
    struct EG
    {
        int to,nxt;
    }e[2*N];
    void ae(int f,int t)
    {
        e[++cnt].to = t;
        e[cnt].nxt = hed[f];
        hed[f] = cnt;
    }
    int fa[N],siz[N],son[N],dep[N],top[N];
    int tin[N],tim;
    void dfs1(int u,int f)
    {
        siz[u]=1;
        fa[u]=f;
        dep[u]=dep[f]+1;
        for(int j=hed[u];j;j=e[j].nxt)
        {
            int to = e[j].to;
            if(to==f)continue;
            dfs1(to,u);
            siz[u]+=siz[to];
            if(siz[to]>siz[son[u]])son[u]=to;
        }
    }
    void dfs2(int u,int tp)
    {
        top[u]=tp;
        tin[u]=++tim;
        if(son[u])
        {
            dfs2(son[u],tp);
            for(int j=hed[u];j;j=e[j].nxt)
            {
                int to = e[j].to;
                if(to==fa[u]||to==son[u])continue;
                dfs2(to,to);
            }
        }
    }
    struct Pair
    {
        db x,y;int id;
        Pair(){}
        Pair(db x,db y,int i):x(x),y(y),id(i){}
        friend bool operator < (Pair a,Pair b)
        {
            if(fabs(a.x-b.x)<eps)return a.y<b.y;
            return a.x<b.x;
        }
    };
    struct segtree
    {
        db x[N],y[N];
        Pair tmp[N];
        int a[200*N],ens[N<<2],beg[N<<2],tm;
        int ct,s[N];
        segtree(){tm=0;}
        void build(int l,int r,int u)
        {
            ct = 0;
            for(int i=l;i<=r;i++)tmp[i] = Pair(x[i],y[i],i);
            sort(tmp+l,tmp+1+r);
            for(int i=l;i<=r;i++)
            {
                while(ct>=2&&(tmp[i].y-y[s[ct]])*(x[s[ct]]-x[s[ct-1]])>(y[s[ct]]-y[s[ct-1]])*(tmp[i].x-x[s[ct]]))
                    ct--;
                s[++ct]=tmp[i].id;
            }
            beg[u]=tm+1;
            for(int i=1;i<=ct;i++)a[++tm]=s[i];
            ens[u]=tm;
            if(l==r)return ;
            int mid = (l+r)>>1;
            build(l,mid,u<<1);
            build(mid+1,r,u<<1|1);
        }
        int ret;
        void div_3(int u,db k)
        {
            int l = beg[u],r = ens[u];
            while(r-l>3)
            {
                int lm = (l+l+r)/3,rm = (l+r+r)/3;
                if(y[a[lm]]-k*x[a[lm]]>y[a[rm]]-k*x[a[rm]])r=rm;
                else l=lm;
            }
            for(int i=l;i<=r;i++)
                if(y[a[i]]-k*x[a[i]]>y[ret]-k*x[ret])ret=a[i];
        }
        void query(int l,int r,int u,int ql,int qr,db k)
        {
            if(l==ql&&r==qr)
            {
                div_3(u,k);
                return ;
            }
            int mid = (l+r)>>1;
            if(qr<=mid)query(l,mid,u<<1,ql,qr,k);
            else if(ql>mid)query(mid+1,r,u<<1|1,ql,qr,k);
            else query(l,mid,u<<1,ql,mid,k),query(mid+1,r,u<<1|1,mid+1,qr,k);
        }
        int get_ret(int x,int y,db k)
        {
            ret = tin[x];
            while(top[x]!=top[y])
            {
                if(dep[top[x]]<dep[top[y]])swap(x,y);
                query(1,n,1,tin[top[x]],tin[x],k);
                x = fa[top[x]];
            }
            if(dep[x]>dep[y])swap(x,y);
            query(1,n,1,tin[x],tin[y],k);
            return ret;
        }
    }tr[2];
    db gt(int x,int y,db k)
    {
        int a = tr[0].get_ret(x,y,k);
        int b = tr[1].get_ret(x,y,k);
        return (tr[0].y[a]+tr[1].y[b])/(tr[0].x[a]+tr[1].x[b]);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%lf",&p1[i].x);
        for(int i=1;i<=n;i++)scanf("%lf",&p1[i].y);
        for(int i=1;i<=n;i++)scanf("%lf",&p2[i].x);
        for(int i=1;i<=n;i++)scanf("%lf",&p2[i].y);
        for(int f,t,i=1;i<n;i++)
        {
            scanf("%d%d",&f,&t);
            ae(f,t),ae(t,f);
        }
        dfs1(1,0),dfs2(1,1);
        for(int i=1;i<=n;i++)
        {
            tr[0].x[tin[i]]=p1[i].x;
            tr[0].y[tin[i]]=p1[i].y;
            tr[1].x[tin[i]]=p2[i].x;
            tr[1].y[tin[i]]=p2[i].y;
        }
        tr[0].build(1,n,1);
        tr[1].build(1,n,1);
        scanf("%d",&m);
        while(m--)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            db las = 2e5 , ans = gt(x,y,las);
            while(fabs(ans-las)>1e-4)
            {
                las = ans;
                ans = gt(x,y,las);
            }
            printf("%.4lf
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    瀑布流布局——JS+绝对定位
    浏览器事件的思考
    css的hack详解
    主流浏览器的Hack写法
    [HTML&CSS] 未知高度多行文本垂直居中
    HTML标签的默认样式列表
    推荐的 CSS 书写顺序
    高效整洁CSS代码原则 (上)
    高效整洁CSS代码原则 (下)
    Xcode升级导致插件失效的解决办法
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10155282.html
Copyright © 2020-2023  润新知