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\n",l);
219     }
220     return 0;
221 }

 

 

 

 
posted @ 2018-12-13 20:58  Unstoppable728  阅读(324)  评论(0编辑  收藏  举报