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移至方程两侧,发现就是一个直线方程寻找最大截距。

凸包没跑了。

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

开两颗线段树存。

代码:

 #include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lll spc<<1
#define rrr spc<<1|1
typedef long long lnt;
const double eps=1e-;
const int N=;
struct trnt{
int l,r;
};
struct data{
double x,y;
bool friend operator < (data a,data b)
{
return a.x<b.x;
}
}tmp[N];
struct pnt{
int hd;
int fa;
int dp;
int tp;
int wgt;
int ind;
int mxs;
double x,y,p,q;
}p[N];
struct ent{
int twd;
int lst;
}e[N<<];
class segment_tree{
public:
void Build(int l,int r,int spc)
{
int bot=tr[spc].l=top+;
for(int i=l;i<=r;i++)
val[++top]=ln[i];
std::sort(val+tr[spc].l,val+top+);
int cel=top;
top=bot;
for(int i=bot+;i<=cel;i++)
{
while(top>bot&&(val[top].y-val[top-].y)*(val[i].x-val[top].x)<(val[i].y-val[top].y)*(val[top].x-val[top-].x)-eps)
top--;
val[++top]=val[i];
}
tr[spc].r=top;
if(l==r)
return ;
int mid=(l+r)>>;
Build(l,mid,lll);
Build(mid+,r,rrr);
return ;
}
double query(int l,int r,int ll,int rr,int spc,double k)
{
if(l>rr||ll>r)
return -1e9;
if(ll<=l&&r<=rr)
{
double ans;
int L=tr[spc].l;
int R=tr[spc].r;
while(L<R)
{
int mid=(L+R)>>;
if(val[mid+].y-val[mid].y<(val[mid+].x-val[mid].x)*k+eps)
{
R=mid;
}else
L=mid+;
}
ans=val[R].y-val[R].x*k;
return ans;
}
int mid=(l+r)>>;
return std::max(query(l,mid,ll,rr,lll,k),query(mid+,r,ll,rr,rrr,k));
}
void Insert(int l,int r,data *a)
{
for(int i=l;i<=r;i++)
ln[i]=a[i];
return ;
}
private:
trnt tr[N];
data ln[N];
data val[N];
int top;
}S[];
int n,m;
int cnt;
int dfn;
void ade(int f,int t)
{
cnt++;
e[cnt].twd=t;
e[cnt].lst=p[f].hd;
p[f].hd=cnt;
return ;
}
void Basic_dfs(int x,int f)
{
p[x].fa=f;
p[x].dp=p[f].dp+;
p[x].wgt=;
int maxs=-;
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(to==f)
continue;
Basic_dfs(to,x);
p[x].wgt+=p[to].wgt;
if(maxs<p[to].wgt)
{
maxs=p[to].wgt;
p[x].mxs=to;
}
}
return ;
}
void Build_dfs(int x,int top)
{
if(!x)
return ;
p[x].ind=++dfn;
p[x].tp=top;
Build_dfs(p[x].mxs,top);
for(int i=p[x].hd;i;i=e[i].lst)
{
int to=e[i].twd;
if(p[to].ind)
continue;
Build_dfs(to,to);
}
return ;
}
int Lca(int x,int y)
{
while(p[x].tp!=p[y].tp)
{
if(p[p[x].tp].dp<p[p[y].tp].dp)
std::swap(x,y);
x=p[p[x].tp].fa;
}
if(p[x].dp>p[y].dp)
std::swap(x,y);
return x;
}
bool check(int x,int y,double lambda)
{
double a=-1e9,b=-1e9;
int z=Lca(x,y);
while(p[x].tp!=p[z].tp)
{
a=std::max(S[].query(,n,p[p[x].tp].ind,p[x].ind,,lambda),a);
b=std::max(S[].query(,n,p[p[x].tp].ind,p[x].ind,,lambda),b);
x=p[p[x].tp].fa;
}
a=std::max(S[].query(,n,p[z].ind,p[x].ind,,lambda),a);
b=std::max(S[].query(,n,p[z].ind,p[x].ind,,lambda),b);
while(p[y].tp!=p[z].tp)
{
a=std::max(S[].query(,n,p[p[y].tp].ind,p[y].ind,,lambda),a);
b=std::max(S[].query(,n,p[p[y].tp].ind,p[y].ind,,lambda),b);
y=p[p[y].tp].fa;
}
a=std::max(S[].query(,n,p[z].ind,p[y].ind,,lambda),a);
b=std::max(S[].query(,n,p[z].ind,p[y].ind,,lambda),b);
return a+b>eps;
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
scanf("%lf",&p[i].x);
for(int i=;i<=n;i++)
scanf("%lf",&p[i].y);
for(int i=;i<=n;i++)
scanf("%lf",&p[i].p);
for(int i=;i<=n;i++)
scanf("%lf",&p[i].q);
for(int i=;i<n;i++)
{
int a,b;
scanf("%d%d",&a,&b);
ade(a,b);
ade(b,a);
}
Basic_dfs(,);
Build_dfs(,);
for(int i=;i<=n;i++)
tmp[p[i].ind]=(data){p[i].x,p[i].y};
S[].Insert(,n,tmp);
for(int i=;i<=n;i++)
tmp[p[i].ind]=(data){p[i].p,p[i].q};
S[].Insert(,n,tmp);
S[].Build(,n,);
S[].Build(,n,);
scanf("%d",&m);
while(m--)
{
int a,b;
scanf("%d%d",&a,&b);
double l=,r=1e8;
while(fabs(l-r)>=1e-)
{
double mid=(l+r)/2.00;
if(check(a,b,mid))
l=mid;
else
r=mid;
}
printf("%.4lf\n",l);
}
return ;
}
 

BZOJ2402: 陶陶的难题II(树链剖分,0/1分数规划,斜率优化Dp)的更多相关文章

  1. [BZOJ2402]陶陶的难题II(树链剖分+线段树维护凸包+分数规划)

    陶陶的难题II 时间限制:40s      空间限制:128MB 题目描述 输入格式 第一行包含一个正整数N,表示树中结点的个数. 第二行包含N个正实数,第i个数表示xi (1<=xi<= ...

  2. BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)

    毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...

  3. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  4. 【模板时间】◆模板·II◆ 树链剖分

    [模板·II]树链剖分 学长给我讲树链剖分,然而我并没有听懂,还是自学有用……另外感谢一篇Blog +by 自为风月马前卒+ 一.算法简述 树链剖分可以将一棵普通的多叉树转为线段树计算,不但可以实现对 ...

  5. BZOJ5210 最大连通子块和 【树链剖分】【堆】【动态DP】

    题目分析: 解决了上次提到的<切树游戏>后,这道题就是一道模板题. 注意我们需要用堆维护子重链的最大值.这样不会使得复杂度变坏,因为每个重链我们只考虑一个点. 时间复杂度$O(nlog^2 ...

  6. 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分

    题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...

  7. BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 14302  Solved: 5779[Submit ...

  8. 树链剖分+线段树 BZOJ 1036 [ZJOI2008]树的统计Count

    题目链接 题意: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节 ...

  9. 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分

    [BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...

随机推荐

  1. Use Uncertainty As a Driver

     Use Uncertainty As a Driver Kevlin Henney ConFRonTEd WiTH TWo opTionS, most people think that the ...

  2. 开源企业IM-免费企业即时通讯-ENTBOOST V0.9版本号公布

    ENTBOOST V0.9版本号公布,更新内容:1.完好多人群组聊天,提高群组聊天性能及稳定性:2.苹果IOS SDK.添加联系人管理功能,优化API和内部流程.修复部分BUG.3.添加企业应用功能集 ...

  3. HDU 1005 Number Sequence(矩阵)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission( ...

  4. TwinCAT 3中基于UDP协议通讯的C++实现

    因为项目需要,学习了TwinCAT3中使用UDP协议进行通讯的基本知识.这个做个简单的笔记,方便以后查询. 1 概述 倍福为了实现从实时环境中直接访问网卡(network cards)专门提供了一个函 ...

  5. C#初学者使用file.creat()创建文件后,显示正由另一进程使用

    string sourcePhotoPath = this.GetUserSelectedPhoto(); if(sourcePhotoPath == null) { return; } string ...

  6. 【Linux下用户和组管理】

    创建用户--useradd . 命令格式:useradd [参数] 用户名 useradd也可写成adduser . 参数如下 -u 指定UID号 -d 指定宿主目录 -e 指定生效时间 -g 指定基 ...

  7. Windows上Python2与Python3同时安装、共存

    一.选择 Python2 还是 Python3?当然是全都要 Python3 虽是未来,不过 Python2 的用户群体仍然膨大,网上有大量优良的项目和模块可供使用,遇到问题也基本可以找到解决方法,推 ...

  8. 洛谷——P1043 数字游戏

    https://www.luogu.org/problem/show?pid=1043 题目描述 丁丁最近沉迷于一个数字游戏之中.这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要 ...

  9. hdu5288 OO’s Sequence 二分 多校联合第一场

    OO's Sequence Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) ...

  10. SWTBOK測试实践系列(1) -- 測试在项眼下期的评审投入划算吗?

    測试策略:静态測试还是动态測试? [对话场景] 成功公布某个软件版本号之后,项目团队召开了项目的经验教训总结大会.在会议期间,项目经理小项和測试经理小測进行了例如以下的对话: 小项:"小測, ...