【bzoj2402】陶陶的难题II
Solution
这题的话,看到答案的形式想到分数规划(Portal -->【learning】)
套路一波,记当前二分的\(mid\)为\(\lambda'\),那么其实就是要快速判断:
&(y_i+q_j)-\lambda'(x_i+p_j)\\
=&(y_i-\lambda' x_i)+(q_j-\lambda' p_j)
\end{aligned}
\]
的最大值与\(0\)的大小关系
上面的这个式子虽然说与\(i\)和\(j\)有关,但是两个部分的形式是完全一样并且相互不影响的,可以看成一个函数\(g\),那么对于每次询问我们只要求出\(x\)到\(y\)路径上的\(g\)然后找最大值和次大值加起来就好了
求\(x\)到\(y\)路径上的信息我们可以考虑用树链剖分,接下来的问题就是怎么求一条重链中所有点的\(g\)的最大值
观察\(g\)的形式:
g(i)&=y_i-\lambda'x_i\\
y_i&=\lambda'x_i+g(i)
\end{aligned}
\]
那其实可以转化成一个这样的问题:求斜率为\(\lambda'\)且过\((x_i,y_i)\)的直线的截距的最大值
容易得出结论最优的\((x_i,y_i)\)一定是在上凸壳上的
那所以我们考虑对于树剖中的线段树的每一个区间,分别维护这个区间中的点对应的\((x_i,y_i)\)和\((q_i,p_i)\)的上凸壳,查询的话直接在上凸壳上二分就好了
一些需要注意的地方:
1、在查询二分的时候,由于题目没有保证任意两个点的\(x,y,p,q\)不相同,所以不能直接用除法,而是应该移下项用乘法判断
2、额如果是用vector存凸包的话。。在求凸包的时候。。要注意下标是从\(0\)开始的!\(0\)开始的!\(0\)开始的!嗯。。
3、然后我的叉积好像写的有点丑了不过!不管了qwq
代码大概长这样
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define Pr pair<double,double>
#define mp make_pair
using namespace std;
const int N=1e5+10,SEG=N*4,inf=2147483647;
const double eps=1e-5;
struct xxx{
int y,nxt;
}a[N*2];
double val[N][4];
int h[N],top[N],son[N],sz[N],pre[N],dep[N];
int lis[N],dfn[N];
int n,m,tot,dfn_t;
void update(Pr &ret,Pr data);
void add(int x,int y);
void dfs1(int fa,int x,int d);
void dfs2(int fa,int x);
bool check(int x,int y,double k);
void solve(int x,int y);
struct Hull{/*{{{*/
vector<Pr> a;
void insert(double x,double y){a.push_back(mp(x,y));}
double chaji(Pr x,Pr y){return x.first*y.second-x.second*y.first;}
void build(){
sort(a.begin(),a.end());
vector<Pr> st;
st.clear();
int top=0;
for (int i=0;i<a.size();++i){
while (top>1&&chaji(mp(a[i].first-st[top-2].first,a[i].second-st[top-2].second),mp(st[top-1].first-st[top-2].first,st[top-1].second-st[top-2].second))<0)
//!!因为是从0开始的所以st的下标都要-1
--top,st.pop_back();
++top; st.push_back(a[i]);
}
a=st;
a.resize(top);
}
double query(double k){
int l=0,r=a.size()-1,mid;
while (l<r){
mid=l+r>>1;
if (a[mid+1].second-a[mid].second<=k*(a[mid+1].first-a[mid].first)) r=mid;
else l=mid+1;
}
return a[l].second-k*a[l].first;
}
void debug(){
for (int i=0;i<a.size();++i) printf("%.2lf %.2lf\n",a[i].first,a[i].second);
}
};/*}}}*/
namespace Seg{/*{{{*/
int ch[SEG][2];
Hull info[SEG][2];
int n,tot;
void _build(int x,int l,int r){
int tmp;
for (int i=l;i<=r;++i){
tmp=lis[i];
info[x][0].insert(val[tmp][0],val[tmp][1]);
info[x][1].insert(val[tmp][2],val[tmp][3]);
}
info[x][0].build(); info[x][1].build();
if (l==r) return;
int mid=l+r>>1;
ch[x][0]=++tot; _build(ch[x][0],l,mid);
ch[x][1]=++tot; _build(ch[x][1],mid+1,r);
}
void build(int _n){n=_n; tot=1; _build(1,1,n);}
Pr _query(int x,int l,int r,int lx,int rx,double k){
if (l<=lx&&rx<=r){
return mp(info[x][0].query(k),info[x][1].query(k));
}
Pr ret=mp(-inf,-inf);
int mid=lx+rx>>1;
if (l<=mid) update(ret,_query(ch[x][0],l,r,lx,mid,k));
if (r>mid) update(ret,_query(ch[x][1],l,r,mid+1,rx,k));
return ret;
}
Pr query(int l,int r,double k){return _query(1,l,r,1,n,k);}
}/*}}}*/
int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int x,y;
scanf("%d",&n);
for (int j=0;j<4;++j)
for (int i=1;i<=n;++i)
scanf("%lf",&val[i][j]);
memset(h,-1,sizeof(h));
tot=0;
for (int i=1;i<n;++i){
scanf("%d%d",&x,&y);
add(x,y); add(y,x);
}
dfs1(0,1,1);
top[1]=1; dfn_t=0;
dfs2(0,1);
Seg::build(n);
scanf("%d",&m);
for (int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
solve(x,y);
}
}
void add(int x,int y){
a[++tot].y=y; a[tot].nxt=h[x]; h[x]=tot;
}
void dfs1(int fa,int x,int d){
int u;
son[x]=0; sz[x]=1; pre[x]=fa; dep[x]=d;
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (u==fa) continue;
dfs1(x,u,d+1);
if (sz[son[x]]<sz[u]) son[x]=u;
sz[x]+=sz[u];
}
}
void dfs2(int fa,int x){
int u;
dfn[x]=++dfn_t; lis[dfn[x]]=x;
if (son[x]){
top[son[x]]=top[x];
dfs2(x,son[x]);
}
for (int i=h[x];i!=-1;i=a[i].nxt){
u=a[i].y;
if (u==fa||u==son[x]) continue;
top[u]=u;
dfs2(x,u);
}
}
bool check(int x,int y,double k){
Pr ret=mp(-inf,-inf);
while (top[x]!=top[y]){
if (dep[top[x]]<dep[top[y]]) swap(x,y);
update(ret,Seg::query(dfn[top[x]],dfn[x],k));
x=pre[top[x]];
}
if (dfn[x]>dfn[y]) swap(x,y);
update(ret,Seg::query(dfn[x],dfn[y],k));
return ret.first+ret.second>0;
}
void update(Pr &ret,Pr data){
ret.first=max(ret.first,data.first);
ret.second=max(ret.second,data.second);
}
void solve(int x,int y){
double l=0,r=1e5,mid,ans;
while (r-l>eps){
mid=(l+r)*0.5;
if (check(x,y,mid)) l=mid;
else r=mid;
}
printf("%.4lf\n",l);
}
【bzoj2402】陶陶的难题II的更多相关文章
- [BZOJ2402]陶陶的难题II(树链剖分+线段树维护凸包+分数规划)
陶陶的难题II 时间限制:40s 空间限制:128MB 题目描述 输入格式 第一行包含一个正整数N,表示树中结点的个数. 第二行包含N个正实数,第i个数表示xi (1<=xi<= ...
- bzoj 2402: 陶陶的难题II 二分答案维护凸包
2402: 陶陶的难题II Time Limit: 40 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 68 Solved: 45[Submi ...
- BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)
前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...
- 【BZOJ2401】陶陶的难题I 欧拉函数+线性筛
[BZOJ2401]陶陶的难题I 题意:求,n<=1000000,T<=100000 题解:直接做是n*sqrt(n)的,显然会TLE,不过这题a和b都是循环到n,那么就可以进行如下的神奇 ...
- bzoj 2401: 陶陶的难题I 数论
2401: 陶陶的难题I Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 89 Solved: 24[Submit][Status] Descript ...
- P1676陶陶吃苹果 - vijos
描述 curimit知道陶陶很喜欢吃苹果.于是curimit准备在陶陶生日的时候送给他一棵苹果树. curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上有c[i]个苹果, ...
- 武汉科技大学ACM:1007: 陶陶摘苹果
Problem Description 厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 个苹果到地面的高度,以及陶陶把手伸直的时候能够达到的最大高度,请帮陶陶算一下她能够摘到的苹 ...
- 洛谷-陶陶摘苹果(升级版)-BOSS战-入门综合练习1
题目描述 Description 又是一年秋季时,陶陶家的苹果树结了n个果子.陶陶又跑去摘苹果,这次她有一个a公分的椅子.当他手够不着时,他会站到椅子上再试试. 这次与NOIp2005普及组第一题不同 ...
- NOIP2005-普及组复赛-第一题-陶陶摘苹果
题目描述 Description 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳 ...
- noip普及组2005 陶陶摘苹果
陶陶摘苹果 描述 陶陶家的院子里有一棵苹果树,每到秋天树上就会结出10个苹果.苹果成熟的时候,陶陶就会跑去摘苹果.陶陶有个30厘米高的板凳,当她不能直接用手摘到苹果的时候,就会踩到板凳上再试试. 现在 ...
随机推荐
- Unity编辑器扩展 Chapter3--Create Custom Inspector
一.Create Custom Inspector 重绘inspector面板一方面是我们的挂在脚本的窗口变得友好,另一方面可以让其变得更强大,比如添加一些有效性验证. 二.重要说明 1.Editor ...
- Python教程 深入条件控制
while 和 if 条件句中可以使用任意操作,而不仅仅是比较操作. 比较操作符 in 和 not in 校验一个值是否在(或不在)一个序列里.操作符 is 和 is not 比较两个对象是不是同一个 ...
- 《疯狂前端开发讲义jQuery+Angular+Bootstrap前端开发实践》学习笔记
<疯狂前端开发讲义jQuery+Angular+Bootstrap前端开发实践>学习笔记 二〇一九年二月十三日星期三2时28分54秒 前提:本书适合有初步HTML.CSS.JavaScri ...
- sqli-labs学习笔记 DAY1
DAY 1 准备工作 安装phpstudy 安装配置sqli-labs 学习笔记 SQL语句的注释:–, # +在URL经过编码后会编码为空格 SQL语句的查询语句:SELECT column_nam ...
- Paper Reading - Long-term Recurrent Convolutional Networks for Visual Recognition and Description ( CVPR 2015 )
Link of the Paper: https://arxiv.org/abs/1411.4389 Main Points: A novel Recurrent Convolutional Arch ...
- 转:为什么说招到合适的人比融到钱更加重要 - Hiring Great Talent is More Important Than Fund Raising
我在猎头行业工作了 20 多年,一直在帮助创业公司招聘优秀的人才.我服务过的客户既有 VC 投资的初创企业,也有即将 IPO 的公司.我和 200 多个 VC 合作过,也见过 300 多个客户失败的案 ...
- JSON.stringify处理对象时的问题
1. JSON.stringify({entry_key: 'test', entry_detail: undefined}) 结果 为 "{"entry_key": & ...
- 遗传算法框架GAFT优化小记
前言 前段时间一直在用自己写的遗传算法框架测试算法在优化力场参数的效果,但是跑起来效率很慢,因为适应度函数需要调用多次力场程序计算能量,但是还是比我预想中的慢我也没有及时对程序进行profiling和 ...
- 根据Unicode码生成汉字
最近需要一批汉字字符数据,类似数字字符与ASCII码之间的对应关系,汉字字符与Unicode码之间也存在对应关系. 所以可以遍历Unicode码批量生成汉字. 其中,汉字为宽字符,输出时候注意需要修改 ...
- 互评Alpha版本——基于NABCD评论作品,及改进建议
组名:可以低头,但没必要 组长:付佳 组员:张俊余 李文涛 孙赛佳 田良 于洋 刘欣 段晓睿 一.杨老师粉丝群--<弹球学成语> 1.1 NABCD分析 N(Need,需求 ...