zoukankan      html  css  js  c++  java
  • bzoj4306: 玩具厂

    Description

    在JIH考察的地图中有N个城市,被公路依次连成了一个环,JIH想在这些城市中建一个玩具厂。城市和公路都被编号为1..N,i号公路连接i-1号城市与i号城市(1号公路连接N号城市与1号城市),每个城市对玩具的需求为wi,每条公路的长度为di。当JIH在第i号城市建玩具厂时,JIH需要将玩具运输到其他城市(当然i城市除外)。设第i号城市到第j号城市的两条路径长度分别为l1、l2,则将玩具运输到第j号城市的费用为l1*l2*wj。总的运输费用为将玩具运到所有城市的运输费用的总和。
    JIH当然想要总的运输费用最少,所以他会选最优的城市建玩具厂,如果有多个最优的城市,小月会等概率的选取其中一个建玩具厂。
    由于JIH的调查工作没做好,只知道1..N-1号城市的wi,而N号城市的wi只知道它的取值范围[a,b],假设wi的值在实数区间[a,b]上的概率是均匀分布的。现在JIH只好去进行第二次调查,于是我们想知道每个城市建玩具厂的概率是多少。
     
     

    Input

    第一行有三个正整数N,a,b。
    接下来N-1行每行一个正实数,为w[1]到w[N-1]。
    接下来N行每行一个正实数,为d[1]到d[N]。
     

    Output

    N行,每行一个实数,表示在第i个城市建厂的概率
     

    Sample Input

    5 1 100
    50
    25
    25
    50
    1
    2
    3
    2
    1

    Sample Output

    0.090
    0.000
    0.000
    0.090
    0.821

    HINT

    当w[5]<18.75时,将在1或4号城市建玩具厂,当w[5]>18.75时,将在5号城市建玩具厂,

    当w[5]=18.75时,将在1或4或5建玩具厂。

    100%的数据中:N<=100000,a<=b<=10000,w[i]<=10000,d[i]<=10。
     
     
    先将每个点的代价表示为kx+b的形式,然后维护个凸包求出每段区间最低的直线,进而求出每条直线即每个点被选的概率。
    现在瓶颈在求出每个点的b。
    如果将厂设在i-1点 l[j],r[j]为i-1点和j点的两条路长度,则
    b[i-1]=Σl[j]*r[j]*w[j]
    同理b[i]=Σ(l[j]+d[i])*(r[j]-d[i])*w[j]
    作差得 b[i]-b[i-1]=Σw[j]*(r[j]*d[i]-l[j]*d[i]-d[i]*d[i])
    =Σw[j]*r[j]*d[i]-Σw[j]*l[j]*d[i]-Σw[j]*d[i]*d[i]
    维护Σw[j]*r[j]Σw[j]*l[j]即可。
    先暴力求出第1个点的b,然后O(1)转移求其他点的b,求所有点的b变成了O(N)。
    注意:有重复的直线,他们要平分概率。
    code:
      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cmath>
      4 #include<cstring>
      5 #include<algorithm>
      6 #define maxn 100005
      7 #define eps 1E-9
      8 #define inf 1E100
      9 using namespace std;
     10 int n,flag,cnt,siz,pos[maxn];
     11 double w[maxn],d[maxn],dist[maxn],tot,tmp,ans,t1,t2,t3,val[maxn];
     12 double a,b,l,r,f[maxn],p[maxn];
     13 struct Line{
     14     double k,b;
     15     int id;
     16 }line[maxn],tl[maxn];
     17 bool cmp(Line x,Line y){
     18     if (abs(x.k-y.k)>eps) return x.k>y.k;
     19     return x.b<y.b;
     20 }
     21 double calc(Line l1,Line l2){return -(l1.b-l2.b)/(l1.k-l2.k);}
     22 struct DATA{
     23     double x;
     24     int id;
     25 }list[maxn];
     26 void solve(){
     27     memcpy(tl,line,sizeof(line));
     28     sort(tl+1,tl+n+1,cmp);
     29     for (int i=1,j,t;i<=n;i=j){
     30         line[++cnt]=tl[i],t=0;
     31         for (j=i;tl[j].k==tl[i].k;j++) if (tl[j].b==tl[i].b) pos[tl[j].id]=cnt,t++;
     32         for (j=i;tl[j].k==tl[i].k;j++) if (tl[j].b==tl[i].b) p[tl[j].id]=1.0/t;
     33     }
     34     list[siz=1]=(DATA){-inf,1};
     35     for (int i=2;i<=cnt;i++){
     36         double t=calc(line[i],line[list[siz].id]);
     37         while (t<list[siz].x) siz--,t=calc(line[i],line[list[siz].id]);
     38         list[++siz]=(DATA){t,i};
     39     }
     40     list[++siz]=(DATA){inf,cnt+1};
     41     l=a,r=b,flag=0;
     42     for (int i=1;i<=siz&&flag!=2;i++){
     43         if (list[i].x>l){
     44             if (!flag) flag=1,f[list[i-1].id]=(list[i].x-l)/(r-l);
     45             else if (flag==1&&list[i].x<r) f[list[i-1].id]=(list[i].x-list[i-1].x)/(r-l);
     46             else if (list[i].x>=r) f[list[i-1].id]=(r-list[i-1].x)/(r-l),flag=2;
     47         }
     48     }
     49     for (int i=1;i<=n;i++) p[i]=f[pos[i]]*p[i];
     50     for (int i=1;i<=n;i++) printf("%.3lf
    ",p[i]);
     51 }
     52 int main(){
     53     scanf("%d%lf%lf",&n,&a,&b);
     54     for (int i=1;i<n;i++) scanf("%lf",&w[i]);
     55     for (int i=1;i<=n;i++) scanf("%lf",&d[i]);
     56     for (int i=1;i<=n;i++) dist[i]=d[i];
     57     for (int i=1;i<=n;i++) dist[i]+=dist[i-1];
     58     tot=dist[n];
     59     if (a==b){
     60         w[n]=a;
     61         t1=w[1]*tot,t3=w[1];
     62         for (int i=2;i<=n;i++){
     63             tmp+=w[i]*(dist[i]-dist[1])*(tot-dist[i]+dist[1]);
     64             t1+=w[i]*(dist[i]-dist[1]);
     65             t2+=w[i]*(tot-dist[i]+dist[1]);
     66             t3+=w[i];
     67         }
     68         val[1]=ans=tmp;
     69         for (int i=2;i<=n;i++){
     70             tmp+=t1*d[i]-t2*d[i]-t3*d[i]*d[i];
     71             ans=min(ans,tmp);
     72             val[i]=tmp;
     73             t1+=w[i]*tot,t2-=w[i]*tot;
     74             t1-=t3*d[i],t2+=t3*d[i];
     75         }
     76         cnt=0;
     77         for (int i=1;i<=n;i++) if (abs(val[i]-ans)<=eps) cnt++;
     78         for (int i=1;i<=n;i++) if (abs(val[i]-ans)<=eps) printf("%.3lf
    ",1.0/cnt);
     79         else puts("0.000");
     80         return 0;
     81     }
     82     l=0,r=tot;
     83     for (int i=1;i<=n;i++) l+=d[i],r-=d[i],line[i].k=l*r;
     84     t1=w[1]*tot,t3=w[1];
     85     for (int i=2;i<=n;i++){
     86         tmp+=w[i]*(dist[i]-dist[1])*(tot-dist[i]+dist[1]);
     87         t1+=w[i]*(dist[i]-dist[1]);
     88         t2+=w[i]*(tot-dist[i]+dist[1]);
     89         t3+=w[i];
     90     }
     91     line[1].b=tmp;
     92     for (int i=2;i<=n;i++){
     93         tmp+=t1*d[i]-t2*d[i]-t3*d[i]*d[i];
     94         line[i].b=tmp;
     95         t1+=w[i]*tot,t2-=w[i]*tot;
     96         t1-=t3*d[i],t2+=t3*d[i];
     97     }
     98     for (int i=1;i<=n;i++) line[i].id=i;
     99     solve();
    100     return 0;
    101 }
  • 相关阅读:
    LeetCode 334 Increasing Triplet
    LeetCode 笔记27 Two Sum III
    LeetCode 笔记28 Maximum Gap
    最小的图灵完备语言——BrainFuck
    蛋疼的SVG外部引用方式
    HackerRank# Hexagonal Grid
    HackerRank# The Longest Common Subsequence
    HackerRank# Bricks Game
    HackerRank# Fibonacci Modified
    HackerRank# Knapsack
  • 原文地址:https://www.cnblogs.com/chenyushuo/p/4922369.html
Copyright © 2011-2022 走看看