洛谷题目传送门

解题思路

首先发现只有xxx和ccc是有用的
这些时空构成了一棵树,我们实际上要找一个点iii,满足对于给出的XXX
min((X−xi)2+ci)min((X-x_i)^2+c_i)min((X−xi​)2+ci​)
根据斜率优化的套路
我们展开式子
ans=(X−xi)2+ci=X2−2xiX+xi2+cians=(X-x_i)^2+c_i=X^2-2x_iX+x_i^2+c_ians=(X−xi​)2+ci​=X2−2xi​X+xi2​+ci​
xi2+ci=ans+2∗xi∗X−X2x_i^2+c_i=ans+2*x_i*X-X^2xi2​+ci​=ans+2∗xi​∗X−X2
那么可以把每个星球看成一个点(2×xi,xi2+ci)(2\times x_i,x_i^2+c_i)(2×xi​,xi2​+ci​)然后用一条斜率为XXX的凸包截这些点,所能获得的最大截距
我们只需要维护一个上凸壳就行了
然后我们就得到了一个思路
我们建立一颗以树的dfsdfsdfs为序列的线段树,这样每个星球存在的范围是若干区间,并对于每个区间都维护一个上凸壳,然后为了更方便的建立凸包,我们先把xxx坐标排序,然后再把每个星球插入到它在线段树上存在的区间里
查询的时候如果在线的话每次可能吧整个凸包遍历一遍
所以我们把这些询问按照询问的斜率排序,然后对于每个节点记录一个cur[x]cur[x]cur[x]表示当前扫描到了这个凸包的那个点,因为排过序了所以不可能访问之前的点,也就是说最多访问整个树的凸包一遍,而每个点最多在O(logn)O(logn)O(logn)个区间里,所以我们的复杂度为O(nlogn)O(nlogn)O(nlogn)
对于怎么处理每个星球在线段树上的区间,可以这样考虑
首先对于dfsdfsdfs序来说,第一个有这个星球的节点就是这个星球出现的位置
所以星球只可能在这个节点的子树内出现了
然后之后每次出现的时候,就代表删除,所以这个点的子树内的点都没有这个星球,记录一下上一次出现的位置,那么当前区间就是[edlast+1,dfni][ed_{last}+1,dfn_i][edlast​+1,dfni​]

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 5e5+7;
typedef double db;
const LL INF = 1e18+7;
inline LL read()
{int X=0; bool flag=1; char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}if(flag) return X;return ~(X-1);
}
int n,m;
LL C[N],X[N];
int note[N];
struct edge
{int y,next;
}e[2*N];
struct point
{LL x,y;
}p[N];
struct Query
{int X,s,id;
}Q[N];
point Point(LL x,LL y)
{return (point){x,y};
}
int link[N],t=0;
void add(int x,int y)
{e[++t].y=y;e[t].next=link[x];link[x]=t;
}
int dfn[N],End[N],tot=0;
vector<int> G[N];
int id[N];
void dfs(int x)
{dfn[x]=++tot;G[note[x]].push_back(x);for(int i=link[x];i;i=e[i].next){int y=e[i].y;dfs(y);}End[x]=tot;
}
bool cmp(int i,int j)
{if(X[i]==X[j]) return C[i]>C[j];return X[i]<X[j];
}
bool cmp2(Query a,Query b)
{return a.X<b.X;
}
vector<int> A[N*4];
db slope(int i,int j)
{return (db)(p[j].y-p[i].y)/(p[j].x-p[i].x);
}
void Add(int k,int i)
{int sz=A[k].size();while(sz>1&&(p[A[k][sz-1]].y-p[A[k][sz-2]].y)*(p[i].x-p[A[k][sz-1]].x)>=(p[i].y-p[A[k][sz-1]].y)*(p[A[k][sz-1]].x-p[A[k][sz-2]].x)){sz--;A[k].pop_back();}A[k].push_back(i);return;
}
void Insert(int k,int l,int r,int L,int R,int i)
{if(L<=l&&r<=R){Add(k,i);return;}int mid=(l+r)>>1;if(L<=mid) Insert(k<<1,l,mid,L,R,i);if(R>mid) Insert(k<<1|1,mid+1,r,L,R,i);
}
int cur[N*4];
LL Ask(int k,int l,int r,int x,int K)
{LL res=INF;int sz=A[k].size();if(sz){while(cur[k]<sz-1&&p[A[k][cur[k]+1]].y-p[A[k][cur[k]]].y<1ll*K*(p[A[k][cur[k]+1]].x-p[A[k][cur[k]]].x)) {++cur[k];}res=p[A[k][cur[k]]].y-p[A[k][cur[k]]].x*K+1ll*K*K;}if(l==r) return res;int mid=(l+r)>>1;if (x<=mid) return min(res,Ask(k<<1,l,mid,x,K));else return min(res,Ask(k<<1|1,mid+1,r,x,K));
}
void Build()
{for(int i=1;i<=n;i++){int x=id[i];if(!G[x].empty()){p[i]=Point(2ll*X[x],1ll*X[x]*X[x]+C[x]);int lst=dfn[G[x][0]];int siz=G[x].size();for(int j=1;j<siz;j++){int y=G[x][j];Insert(1,1,n,lst,dfn[y]-1,i);lst=End[y]+1;}if(lst<=End[G[x][0]]) Insert(1,1,n,lst,End[G[x][0]],i);}}
}
LL Ans[N];
int main()
{n=read();m=read();C[1]=read();note[1]=1;for(int i=2;i<=n;i++){int opt=read(),ex;if(opt==0){int Fa=read()+1,id=read()+1;X[id]=read();ex=read();ex=read();C[id]=read();add(Fa,i);note[i]=id;}else{int Fa=read()+1,id=read()+1;add(Fa,i);note[i]=id;}}dfs(1);for(int i=1;i<=n;i++) id[i]=i;sort(id+1,id+n+1,cmp);Build();for(int i=1;i<=m;i++){int s=read()+1,x=read();Q[i]=(Query){x,dfn[s],i};}sort(Q+1,Q+m+1,cmp2);for(int i=1;i<=m;i++)Ans[Q[i].id]=Ask(1,1,n,Q[i].s,Q[i].X);for(int i=1;i<=m;i++)printf("%lld\n",Ans[i]);return 0;
}

[CTSC2016]时空旅行(斜率优化+线段树分治)相关推荐

  1. 【uoj】198:【CTSC2016】时空旅行-dfs序线段树凸包

    传送门:uoj198 题解 y,z坐标无用. 先化简一下式子,假设选择的是第iii个星球,其x" role="presentation" style="posi ...

  2. 时空旅行(dfs序+线段树分治+斜率优化)

    时空旅行 题意: 给定一棵以000为根的树,每个节点上有信息(一种是增加某个带权三维点,一种是删除某个带权三维点):询问要求从根节点到某个节点的信息总和中找到一个最优带权三维点. 思路: 首先,每个星 ...

  3. [CTSC2016]时空旅行 (线段树分治)

    前言 昨天学习了线段树分治,算法比较抽象,没有学得太具体,今天做一道例题练练手 --自闭前 题面上洛谷 题意 维护若干个集合,每个集合都是由一个编号比它小的集合加入一个二元组(x,c)(x,c)(x, ...

  4. 时空旅行[线段树分治][维护凸壳]

    文章目录 前言 题目 思路 代码 前言 肝了一上午-这是我才学线段树分治的例题-真舒服 题目 温馨提示:首先在UOJ做,LOJ挖数据,BZOJ终极评测... UOJ198 二手剽- 思路 为什么不能用 ...

  5. CF981E Addition on Segments 线段树分治 + bitset优化

    传送门 文章目录 题意: 思路: 题意: 思路: 我们考虑如果我们选择的区间都包含某个位置,那么这个位置一定是最大值.那么对于每个位置,我们枚举包含其的区间,让后每次加xxx都用bitsetbitse ...

  6. UOJ#198 [CTSC2016]时空旅行

    题目 UOJ#198 [CTSC2016]时空旅行 题解 QAQ允许我做一个悲伤的表情.这题题解真少.我要做一个造福人类的人. 首先呢可以看出,如果把每个时空当做一个节点,这是棵树,每个节点有一个添加 ...

  7. [CTSC2016]时空旅行

    一.题目 点此看题 二.解法 可以看出这些平行时空呈树形结构,每个星球都会出现在一段连续的dfndfndfn序中,而我们正是要对每个时空的星球中找最小值,那么可以把星球打在dfndfndfn的线段树上 ...

  8. 【BZOJ4025】二分图(可撤销并查集+线段树分治)

    题目: BZOJ4025 分析: 定理:一个图是二分图的充要条件是不存在奇环. 先考虑一个弱化的问题:保证所有边出现的时间段不会交叉,只会包含或相离. 还是不会?再考虑一个更弱化的问题:边只会出现不会 ...

  9. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

最新文章

  1. iOS RunLoop简介
  2. oracle负载均衡方案,Oracle负载均衡配置代码
  3. 阿里巴巴启动2017全球创客大赛 四大洲共设25个赛区
  4. 2013年2月28日星期四
  5. M8100-Table T169P: entry 1510 does not exist
  6. python和javascript哪个好_Python
  7. NetCore下模拟和使用Modbus工业通信协议
  8. Modelsim 后仿真操作步骤之二——用Modelsim单独进行后仿真
  9. linux中文件大小设置函数,truncate函数和ftruncate修改文件大小-linux
  10. Java内部类手机专卖店_Java:内部类
  11. 求锤得锤,你要的一致性 hash 来了! | 附代码
  12. C# 解析 Json数据
  13. udev介绍及两个小场景应用
  14. C语言职工工资管理系统
  15. miRNA数据库篇——mirBase(序列数据库)
  16. 推荐一个有效清理电脑桌面广告、流氓软件的方法
  17. 空间,线性空间,赋范空间,内积空间和希尔伯特空间的区别
  18. api接口安全验证(sign签名和token验证)
  19. 力争群雄:2012年度IT博客大赛100强脱颖而出
  20. Github Action入门

热门文章

  1. 比例阀为什么需要比例阀放大器
  2. CPU, GPU, FPGA计算能力
  3. 页面验证是否是真实有效的身份证号码
  4. Leetcode hot100题 个人整理版
  5. 怎样在Mac上查找WiFi密码并在iPhone上共享它?
  6. 爬虫问题小记 --- UnicodeEncodeError: 'gbk' codec can't encode character '\xa9' in position 25703: illegal
  7. 数据中台当前与未来-数字化架构设计(1)
  8. 抖音新号怎么快速涨粉(8种抖音运营吸粉技巧)
  9. html 数字变成图片,从100到1000数字表图片
  10. 项目上线后,接口报错:SELECT command denied to user ‘用户名’ @ localhost‘ for table ‘ ‘