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
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
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)的更多相关文章
- [BZOJ2402]陶陶的难题II(树链剖分+线段树维护凸包+分数规划)
陶陶的难题II 时间限制:40s 空间限制:128MB 题目描述 输入格式 第一行包含一个正整数N,表示树中结点的个数. 第二行包含N个正实数,第i个数表示xi (1<=xi<= ...
- BZOJ 2402 陶陶的难题II (树链剖分、线段树、凸包、分数规划)
毒瘤,毒瘤,毒瘤-- \(30000\)这个数据范围,看上去就是要搞事的啊... 题目链接: https://www.lydsy.com/JudgeOnline/problem.php?id=2402 ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- 【模板时间】◆模板·II◆ 树链剖分
[模板·II]树链剖分 学长给我讲树链剖分,然而我并没有听懂,还是自学有用……另外感谢一篇Blog +by 自为风月马前卒+ 一.算法简述 树链剖分可以将一棵普通的多叉树转为线段树计算,不但可以实现对 ...
- BZOJ5210 最大连通子块和 【树链剖分】【堆】【动态DP】
题目分析: 解决了上次提到的<切树游戏>后,这道题就是一道模板题. 注意我们需要用堆维护子重链的最大值.这样不会使得复杂度变坏,因为每个重链我们只考虑一个点. 时间复杂度$O(nlog^2 ...
- 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分
题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...
- BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]【学习笔记】
1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 14302 Solved: 5779[Submit ...
- 树链剖分+线段树 BZOJ 1036 [ZJOI2008]树的统计Count
题目链接 题意: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节 ...
- 【BZOJ1036】[ZJOI2008]树的统计Count 树链剖分
[BZOJ1036][ZJOI2008]树的统计Count Description 一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w.我们将以下面的形式来要求你对这棵树完成一些操作: I. ...
随机推荐
- css如何实现垂直居中(5种方法)
css如何实现垂直居中(5种方法) 一.总结 一句话总结:行内只需要简单地把 line-height 设置为那个对象的 height 值就可以使文本居中了. 块的话可以尝试 margin:auto: ...
- hdoj--2682--Tree()
Tree Time Limit: 6000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submi ...
- BZOJ 1193 搜索+贪心
预处理出100*100以内的最优解 贪心走日 判断是0*4还是2*4 搞定 //By SiriusRen #include <queue> #include <cstdio> ...
- SCOPE_IDENTITY()和 SELECT @@IDENTITY 的用法
这俩个,是在插入数据的时候使用,返回刚刚插入数据行的ID 大家慎用@@IDENTITY,而尽量采用 SCOPE_IDENTITY() 函数替换之. SCOPE_IDENTITY() 也是得到最后一条 ...
- [Chromium文档转载,第005章]Calling Mojo from Blink
For Developers > Design Documents > Mojo > Calling Mojo from Blink Variants Let's as ...
- box-shadow制作各种单边,多边阴影
一.box-shadow问题探究 box-shadow 在MDN定义以及详解: box-shadow 以由逗号分隔的列表来描述一个或多个阴影效果.该属性让你可以对几乎所有元素的边框产生阴影.如果元素同 ...
- AtCoderAGC003D Anticube
Description: 给定一个序列\(a\),要求选出最多的序列元素并保证两两元素的乘积不为立方数 Solution: 我们考虑哪些因子是有用的,如果一个因子的指数\(>3\),我们可以将他 ...
- Swift实战(2)--在工程中添加object-C的类或者第三方框架(附翻译)
原文地址:http://stackoverflow.com/questions/24002369/how-to-call-objective-c-code-from-swift Using Objec ...
- 关于命令行签名时.SF和.RSA文件的命名问题
准备工作: 签名文件名称为android.keystore 签名的别名为123456789.keystore 1.使用签名命令后例如以下图 发现.SF和.RSA文件自己主动命名为12345678.SF ...
- pipPython运维日记
一 Python 工作环境管理 1.1 使用 pyenv 管理不同的Python 版本 克隆项目安装 git clone https://github.com/yyuu/pyenv.git ~/.py ...