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\n",ans);
    }
    return 0;
}

 

posted @ 2018-12-21 13:38  LiGuanlin  阅读(201)  评论(0编辑  收藏  举报