zoukankan      html  css  js  c++  java
  • BZOJ2402: 陶陶的难题II(树链剖分,0/1分数规划,斜率优化Dp)

    Description

    Input

    第一行包含一个正整数N,表示树中结点的个数。
    第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5)。
    第三行包含N个正实数,第i个数表示yi (1<=yi<=10^5)。
    第四行包含N个正实数,第i个数表示pi (1<=pi<=10^5)。
    第五行包含N个正实数,第i个数表示qi (1<=qi<=10^5)。
    下面有N-1行,每行包含两个正整数a,b(1<=a,b<=N),表示树中的边。
    第N+5行包含一个正整数M,表示询问的个数。
    最后M行,每行包含正整数a,b(1<=a,b<=N),表示一次询问。

    Output

    共M行,每行一个实数,第i行的数表示第i次询问的答案。
    只要你的输出和我们的输出相差不超过0.001即为正确。

    Sample Input

    5
    3.0 1.0 2.0 5.0 4.0
    5.0 2.0 4.0 3.0 1.0
    1.0 3.0 2.0 4.0 5.0
    3.0 4.0 2.0 1.0 4.0
    1 2
    1 3
    2 4
    2 5
    4
    2 3
    4 5
    2 4
    3 5

    Sample Output

    2.5000
    1.5000
    1.5000
    2.5000

    解题思路:

    那个式子非常像0/1分数规划。

    发现pq式子和xy的式子结构相同,所以用同一种方法维护。

    二分答案,看表达式的值。

    为了寻找最大值可以将x与y移至方程两侧,发现就是一个直线方程寻找最大截距。

    凸包没跑了。

    将树链上的点维护成凸包二分答案取值。

    开两颗线段树存。

    代码:

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define lll spc<<1
      6 #define rrr spc<<1|1
      7 typedef long long lnt;
      8 const double eps=1e-9;
      9 const int N=300000;
     10 struct trnt{
     11     int l,r;
     12 };
     13 struct data{
     14     double x,y;
     15     bool friend operator < (data a,data b)
     16     {
     17         return a.x<b.x;
     18     }
     19 }tmp[N];
     20 struct pnt{
     21     int hd;
     22     int fa;
     23     int dp;
     24     int tp;
     25     int wgt;
     26     int ind;
     27     int mxs;
     28     double x,y,p,q;
     29 }p[N];
     30 struct ent{
     31     int twd;
     32     int lst;
     33 }e[N<<1];
     34 class segment_tree{
     35     public:
     36         void Build(int l,int r,int spc)
     37         {
     38             int bot=tr[spc].l=top+1;
     39             for(int i=l;i<=r;i++)
     40                 val[++top]=ln[i];
     41             std::sort(val+tr[spc].l,val+top+1);
     42             int cel=top;
     43             top=bot;
     44             for(int i=bot+1;i<=cel;i++)
     45             {
     46                 while(top>bot&&(val[top].y-val[top-1].y)*(val[i].x-val[top].x)<(val[i].y-val[top].y)*(val[top].x-val[top-1].x)-eps)
     47                     top--;
     48                 val[++top]=val[i];
     49             }
     50             tr[spc].r=top;
     51             if(l==r)
     52                 return ;
     53             int mid=(l+r)>>1;
     54             Build(l,mid,lll);
     55             Build(mid+1,r,rrr);
     56             return ;
     57         }
     58         double query(int l,int r,int ll,int rr,int spc,double k)
     59         {
     60             if(l>rr||ll>r)
     61                 return -1e9;
     62             if(ll<=l&&r<=rr)
     63             {
     64                 double ans;
     65                 int L=tr[spc].l;
     66                 int R=tr[spc].r;
     67                 while(L<R)
     68                 {
     69                     int mid=(L+R)>>1;
     70                     if(val[mid+1].y-val[mid].y<(val[mid+1].x-val[mid].x)*k+eps)
     71                     {
     72                         R=mid;
     73                     }else
     74                         L=mid+1;
     75                 }
     76                 ans=val[R].y-val[R].x*k;
     77                 return ans;
     78             }
     79             int mid=(l+r)>>1;
     80             return std::max(query(l,mid,ll,rr,lll,k),query(mid+1,r,ll,rr,rrr,k));
     81         }
     82         void Insert(int l,int r,data *a)
     83         {
     84             for(int i=l;i<=r;i++)
     85                 ln[i]=a[i];
     86             return ;
     87         }
     88     private:
     89         trnt tr[N];
     90         data ln[N];
     91         data val[N];
     92         int top;
     93 }S[2];
     94 int n,m;
     95 int cnt;
     96 int dfn;
     97 void ade(int f,int t)
     98 {
     99     cnt++;
    100     e[cnt].twd=t;
    101     e[cnt].lst=p[f].hd;
    102     p[f].hd=cnt;
    103     return ;
    104 }
    105 void Basic_dfs(int x,int f)
    106 {
    107     p[x].fa=f;
    108     p[x].dp=p[f].dp+1;
    109     p[x].wgt=1;
    110     int maxs=-1;
    111     for(int i=p[x].hd;i;i=e[i].lst)
    112     {
    113         int to=e[i].twd;
    114         if(to==f)
    115             continue;
    116         Basic_dfs(to,x);
    117         p[x].wgt+=p[to].wgt;
    118         if(maxs<p[to].wgt)
    119         {
    120             maxs=p[to].wgt;
    121             p[x].mxs=to;
    122         }
    123     }
    124     return ;
    125 }
    126 void Build_dfs(int x,int top)
    127 {
    128     if(!x)
    129         return ;
    130     p[x].ind=++dfn;
    131     p[x].tp=top;
    132     Build_dfs(p[x].mxs,top);
    133     for(int i=p[x].hd;i;i=e[i].lst)
    134     {
    135         int to=e[i].twd;
    136         if(p[to].ind)
    137             continue;
    138         Build_dfs(to,to);
    139     }
    140     return ;
    141 }
    142 int Lca(int x,int y)
    143 {
    144     while(p[x].tp!=p[y].tp)
    145     {
    146         if(p[p[x].tp].dp<p[p[y].tp].dp)
    147             std::swap(x,y);
    148         x=p[p[x].tp].fa;
    149     }
    150     if(p[x].dp>p[y].dp)
    151         std::swap(x,y);
    152     return x;
    153 }
    154 bool check(int x,int y,double lambda)
    155 {
    156     double a=-1e9,b=-1e9;
    157     int z=Lca(x,y);
    158     while(p[x].tp!=p[z].tp)
    159     {
    160         a=std::max(S[0].query(1,n,p[p[x].tp].ind,p[x].ind,1,lambda),a);
    161         b=std::max(S[1].query(1,n,p[p[x].tp].ind,p[x].ind,1,lambda),b);
    162         x=p[p[x].tp].fa;
    163     }
    164     a=std::max(S[0].query(1,n,p[z].ind,p[x].ind,1,lambda),a);
    165     b=std::max(S[1].query(1,n,p[z].ind,p[x].ind,1,lambda),b);
    166     while(p[y].tp!=p[z].tp)
    167     {
    168         a=std::max(S[0].query(1,n,p[p[y].tp].ind,p[y].ind,1,lambda),a);
    169         b=std::max(S[1].query(1,n,p[p[y].tp].ind,p[y].ind,1,lambda),b);
    170         y=p[p[y].tp].fa;
    171     }
    172     a=std::max(S[0].query(1,n,p[z].ind,p[y].ind,1,lambda),a);
    173     b=std::max(S[1].query(1,n,p[z].ind,p[y].ind,1,lambda),b);
    174     return a+b>eps;
    175 }
    176 int main()
    177 {
    178     scanf("%d",&n);
    179     for(int i=1;i<=n;i++)
    180         scanf("%lf",&p[i].x);
    181     for(int i=1;i<=n;i++)
    182         scanf("%lf",&p[i].y);
    183     for(int i=1;i<=n;i++)
    184         scanf("%lf",&p[i].p);
    185     for(int i=1;i<=n;i++)
    186         scanf("%lf",&p[i].q);
    187     for(int i=1;i<n;i++)
    188     {
    189         int a,b;
    190         scanf("%d%d",&a,&b);
    191         ade(a,b);
    192         ade(b,a);
    193     }
    194     Basic_dfs(1,1);
    195     Build_dfs(1,1);
    196     for(int i=1;i<=n;i++)
    197         tmp[p[i].ind]=(data){p[i].x,p[i].y};
    198     S[0].Insert(1,n,tmp);
    199     for(int i=1;i<=n;i++)
    200         tmp[p[i].ind]=(data){p[i].p,p[i].q};
    201     S[1].Insert(1,n,tmp);
    202     S[0].Build(1,n,1);
    203     S[1].Build(1,n,1);
    204     scanf("%d",&m);
    205     while(m--)
    206     {
    207         int a,b;
    208         scanf("%d%d",&a,&b);
    209         double l=0,r=1e8;
    210         while(fabs(l-r)>=1e-5)
    211         {
    212             double mid=(l+r)/2.00;
    213             if(check(a,b,mid))
    214                 l=mid;
    215             else
    216                 r=mid;
    217         }
    218         printf("%.4lf
    ",l);
    219     }
    220     return 0;
    221 }
     
  • 相关阅读:
    JAVA 基础 / 第二十三课: 类和对象 / 什么是JAVA中的方法重载? 构造方法?
    JAVA 基础 / 第二十二课: 类和对象 / 什么是JAVA中的引用? 继承 ?
    【Oracle】ORA-12518, TNS:listener could not hand off client connection
    Oracle 将当前系统时间戳插入timestamp字段 无效的月份
    Git本地有未提交文件,直接拉取远端最新版本
    Windows下分布式环境搭建以及简单测试
    Python——pip快速下载第三方库到指定环境
    Python——Scrapy爬取链家网站所有房源信息
    Python——XPath提取某个标签下所有文本
    Python——全国瓜子二手车数据分析
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/10116386.html
Copyright © 2011-2022 走看看