文章目录

  • 前言
  • 题目
  • 思路
  • 代码

前言

肝了一上午…这是我才学线段树分治的例题…真舒服

题目

温馨提示:首先在UOJ做,LOJ挖数据,BZOJ终极评测。。。
UOJ198

二手剽…

思路

为什么不能用 CDQCDQCDQ 分治做?因为无法减去一个操作的影响(一些计数类型的就可以),或者说信息没有可减性,无法进行转化
考虑线段树合并,如何转化为一个星球的作用时间?
这里的’时间’并不是一个具体的时间,而是 dfsdfsdfs 序
所有版本构成一个树形结构,那么对于一个星球而言,一次加操作就是在 [dfnu,dfnu+sizu−1][dfn_u,dfn_u+siz_u-1][dfnu​,dfnu​+sizu​−1] 的区间加,删除同理
但是实际过程中因为题目输入比较特殊,所以可以通过 DFSDFSDFS 时后一些小操作避免删除(不是重点)
然后通过将修改操作转化为 O(n)O(n)O(n) 段连续的,分在 O(nlogn)O(nlogn)O(nlogn) 个线段树节点上
现在就是区间修改,一些单点询问,并且单先询问带限制(即你是拿着 x0x_0x0​ 去询问的)
考虑处理限制:

min{(x−x0)2+c}min\{(x-x_0)^2+c\}min{(x−x0​)2+c} 平方项的出现优先考虑斜率凸包相关
min{(x−x0)2+c}=min{−2x0x+x2+c}+x02min\{(x-x_0)^2+c\}=min\{-2 x_0x+x^2+c\}+x_0^2min{(x−x0​)2+c}=min{−2x0​x+x2+c}+x02​
令 b=−2x0xi+xi2+cib=-2x_0x_i+x_i^2+c_ib=−2x0​xi​+xi2​+ci​
2x0xi+b=xi2+ci2x_0x_i+b=x_i^2+c_i2x0​xi​+b=xi2​+ci​ ,求 bminb_{min}bmin​

将每个星球看作 (xi,xi2+ci)(x_i,x_i^2+c_i)(xi​,xi2​+ci​) 即是求以 k=2x0k=2x_0k=2x0​ 过点的最小截距,维护下凸壳

由于线段树分治已经将修改覆盖相关询问,就能改变一个节点内修改操作的顺序
我选择修改按斜率递减排序,坐标递增排序,单调栈维护就能做到均摊 O(nlogn)O(nlogn)O(nlogn)
所以总的时间复杂度 O(nlogn)O(nlogn)O(nlogn)
一些细节:
对于横坐标 xix_ixi​ 相等的点我们取 yiy_iyi​ 最小的,返回斜率是注意判断
一些问题:
1.BZOJ老化后我卡常卡得丧心病狂
2.还可以用凸包优化…

代码

#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("inline", "no-stack-protector", "unroll-loops")
#pragma GCC diagnostic error "-fwhole-program"
#pragma GCC diagnostic error "-fcse-skip-blocks"
#pragma GCC diagnostic error "-funsafe-loop-optimizations"
#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstring>
#include<climits>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
inline LL read() {bool f=0;LL x=0;char c=getchar();while(c<'0'||'9'<c){if(c==EOF)exit(0);if(c=='-')f=1;c=getchar();}while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();return !f?x:-x;
}
#define MAXN 500000
#define INF 100000000000000ll
struct node{int type,id;
}a[MAXN+5];
struct Modify{int L,R;LL x,y;friend bool operator < (Modify a,Modify b){return a.x<b.x;}
}M[MAXN+5];
struct Ask{int id,t,x0;friend bool operator < (Ask a,Ask b){return a.x0>b.x0;}
}Q[MAXN+5];
int cntm;
LL x[MAXN+5],c[MAXN+5];
int cnt_dfn,dfn[MAXN+5],siz[MAXN+5];
struct Node{struct Edge{int nxt,v;}edge[2*MAXN+5];int ecnt,head[MAXN+5];void Addedge(int u,int v){edge[++ecnt]=(Edge){head[u],v},head[u]=ecnt;return ;}
}G,ML,MR;
inline void DFS(register int u){siz[u]=1,dfn[u]=++cnt_dfn;if(!a[u].type) ML.Addedge(a[u].id,dfn[u]);else MR.Addedge(a[u].id,dfn[u]-1);for(register int i=G.head[u];i;i=G.edge[i].nxt){register int v=G.edge[i].v;DFS(v),siz[u]+=siz[v];}if(!a[u].type) MR.Addedge(a[u].id,dfn[u]+siz[u]-1);else ML.Addedge(a[u].id,dfn[u]+siz[u]);return ;
}
#define lch (u<<1)
#define rch (u<<1|1)
int siz_Stk[4*MAXN+5];
vector<int> Stk[4*MAXN+5];
inline LL Y(register int i,register int j){return M[i].y-M[j].y;}
inline LL X(register int i,register int j){return M[i].x-M[j].x;}
double K(int i,int j){if(M[i].x==M[j].x)return M[i].y>M[j].y?INF:-INF;return 1.0*(Y(i,j))/(X(i,j));
}
inline void Insert_M(register int u,register int L,register int R,register int qL,register int qR,register int id){if(qL<=L&&R<=qR){register int tp=siz_Stk[u]-1;while(tp>0&&Y(id,Stk[u][tp])*X(Stk[u][tp],Stk[u][tp-1])<=Y(Stk[u][tp],Stk[u][tp-1])*X(id,Stk[u][tp]))//while(tp>0&&K(id,Stk[u][tp])<=K(Stk[u][tp],Stk[u][tp-1]))tp--,Stk[u].pop_back(),siz_Stk[u]--;Stk[u].push_back(id),siz_Stk[u]++;return ;}register int Mid=(L+R)>>1;if(qL<=Mid)Insert_M(lch,L,Mid,qL,qR,id);if(Mid+1<=qR)Insert_M(rch,Mid+1,R,qL,qR,id);return ;
}
LL ans[MAXN+5];
inline LL Query(int u,int L,int R,int p,LL x0){int tp=siz_Stk[u]-1;register LL ret=INF;while(tp>0&&2*x0*X(Stk[u][tp],Stk[u][tp-1])<=Y(Stk[u][tp],Stk[u][tp-1]))//while(tp>0&&2*x0<=K(Stk[u][tp],Stk[u][tp-1]))tp--,Stk[u].pop_back(),siz_Stk[u]--;if(tp!=-1)ret=M[Stk[u][tp]].y-2*x0*M[Stk[u][tp]].x+x0*x0;if(L==R) return ret;register int Mid=(L+R)>>1;if(p<=Mid)ret=min(ret,Query(lch,L,Mid,p,x0));else ret=min(ret,Query(rch,Mid+1,R,p,x0));return ret;
}
int main(){int n=read(),m=read();x[1]=0,c[1]=read();a[1]=(node){0,1};for(int i=2;i<=n;i++){int opt=read();int fr=read()+1,id=read()+1;G.Addedge(fr,i);if(opt==0)x[id]=read(),read(),read(),c[id]=read();a[i]=(node){opt,id};}DFS(1);//puts("");for(register int i=1;i<=n;i++)for(register int j1=ML.head[i],j2=MR.head[i];j1;j1=ML.edge[j1].nxt,j2=MR.edge[j2].nxt){//printf("%d %d\n",ML.edge[j1].v,ML.edge[j2].v);M[++cntm]=(Modify){ML.edge[j1].v,MR.edge[j2].v,x[i],x[i]*x[i]+c[i]};}sort(M+1,M+cntm+1);for(int i=1;i<=cntm;i++)Insert_M(1,1,n,M[i].L,M[i].R,i);for(int i=1;i<=m;i++){int t=read()+1,x0=read();Q[i]=(Ask){i,t,x0};}sort(Q+1,Q+m+1);for(int i=1;i<=m;i++)ans[Q[i].id]=Query(1,1,n,dfn[Q[i].t],Q[i].x0);for(int i=1;i<=m;i++)printf("%lld\n",ans[i]);return 0;
}

时空旅行[线段树分治][维护凸壳]相关推荐

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

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

  2. [CTSC2016]时空旅行(线段树+凸包)

    应该是比较套路的,但是要A掉仍然不容易. 下面理一下思路,思路清楚了也就不难写出来了. 0.显然y,z坐标是搞笑的,忽略即可. 1.如果x不变,那么直接set即可解决. 2.考虑一个空间和询问x0,通 ...

  3. 20200731 SCOI模拟T3(线段树分治)

    T3 越野赛车问题 思路: 将 l,rl,rl,r 用线段树分治维护 用并查集维护连通性 维护最长链可以对每个连通块记录最长链两端点 合并时设两端点分别是 s,ts,ts,t 和 x,yx,yx,y ...

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

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

  5. LOJ 121 「离线可过」动态图连通性——LCT维护删除时间最大生成树 / 线段树分治...

    题目:https://loj.ac/problem/121 离线,LCT维护删除时间最大生成树即可.注意没有被删的边的删除时间是 m+1 . 回收删掉的边的节点的话,空间就可以只开 n*2 了. #i ...

  6. bzoj 4025 二分图——线段树分治+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...

  7. 线段树分治 ---- F. Extending Set of Points(线段树分治 + 可撤销并查集)

    题目链接 题目大意: 你有个点集合SSS,每次往集合里面加点或者删点(如果要加的点出现过),如果(x1,y1),(x2,y1),(x1,y2),(x2,y2)(x1,y1),(x2,y1),(x1,y ...

  8. 线段树分治 ---- CF1217F - Forced Online Queries Problem(假离线 可撤销并查集 + 线段树分治)详解

    题目链接 题目大意 解题思路: 我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是O(n2)O(n^2)O(n2) 首先我们考虑这种动态加边删边 ...

  9. 3237: [Ahoi2013]连通图 线段树分治

    题解: cf765f cf671e bzoj4184 bzoj4552 线段树分治裸题 还是介绍一下线段树分治 这个东西其实挺简单但也挺有用的 可以把删除+插入操作变成只有插入(倒着就是删除) 像这一 ...

最新文章

  1. 7号团队-团队任务3:每日例会(2018-11-29)
  2. Angular 内容投影 content projection 的一个问题的单步调试
  3. string转成对象_详解Java I/O流(五),对象序列化
  4. 使用WSO2 ESB进行邮件内容过滤
  5. 【CodeForces - 527C】Glass Carving(线段树或者SBT或者set)
  6. 一拍即合、一见钟情之后,智慧城市的“福利”来啦……
  7. 使用JS清空fileupload 控件值
  8. mac在命令行里获取root权限
  9. Redis Topic说明
  10. java html写入到word文档_java 使用jacob将html页面写入word
  11. Windows编程的Notification和Message
  12. GDKOI2018游记
  13. [NOIP2006] 能量项链
  14. 马化腾回应《腾讯没有梦想》:我的理想不是赚多少钱
  15. JetBrains:webstrom中代码模板设置
  16. 码力十足学量化|如何获取指数成分股及权重数据
  17. 金融壹账通冲刺港股:9个月亏10亿 半年前刚换帅
  18. element-ui 表格合并问题
  19. 【阿里云总监课】存储系统设计——NVMe SSD性能影响因素一探究竟
  20. Android从一个应用程序启动第三方应用app

热门文章

  1. HDU1788 【中国剩余定理】
  2. Proteus仿真——用两片74HC148及少量逻辑门构成16线--4线优先级编译器
  3. c++空指针的定义-0L
  4. 多元回归分析的心得(笔记)
  5. 2D shape decompositions二维形状分解
  6. 2017字节跳动秋招编程题-头条校招
  7. u盘电视测试软件,智能电视无法识别U盘里的APK文件?当贝市场教你搞定
  8. 对给定的10个国家名,按其字母的顺序输出。C++
  9. C-V2X在国内车路协同的应用
  10. rst 格式文档编译方案