题目链接

题目大意

有 \(n\) 个平行宇宙,由某些平行宇宙添加或删除一个点(三维坐标)得到,

现在有 \(m\) 组询问,形如对于某个平行宇宙,费用为从该平行宇宙内某个点出发

到达指定 \(x\) 坐标的任意位置的欧几里得距离,

并且这些点本身出发需要费用,如何让费用最小,

保证原点在所有平行宇宙中均存在

解题过程

首先 \(x\) 坐标指定那么其实 \(y\) 坐标和 \(z\) 坐标可以被忽略,

那么询问可以转化为形如找到一个存在的 \(x\) ,

使得 \(y=(x-x_0)^2+d\)最小,其中\(d\)表示从这个 \(x\) 出发本身所需费用

把这个平方拆开可以得到 \(y=x^2-2x\cdot x_0 + {x_0}^2+d\)

将常数项放前面可以得到 \({x_0}^2=2x_0\cdot x-x^2+y-d\)

也就是各点坐标为\((2x,-x^2+d)\),用斜率为 \(x_0\) 的直线扫描使得截距最小,那么这也就是求一个下凸壳

然后考虑平行宇宙怎么做,它会形成一棵树,那么点的存在就会锁定在一些dfs序的连续区间中,

也就可以转化成线段树维护dfs序的区间,点按横坐标为第一关键字,纵坐标为第二关键字排序,

如果强制在线询问的话那么就二分答案需要多带一个\(\log\),

否则可以按照斜率排序那么直接删除队头即可,时间复杂度\(O(m\log_2n)\)

代码

#include <cstdio>
#include <cctype>
#include <algorithm>
#include <vector>
#define rr register
using namespace std;
const int N = 500011;
typedef long long lll;
struct Point {
lll x, y;
inline Point operator -(const Point &t)const {
return (Point) {
x - t.x, y - t.y
};
}
} a[N];
struct rec {
int x, z, rk;
} q[N];
struct node {
int y, next;
} e[N];
vector<int>L[N], R[N];
vector<Point>K[N << 2];
lll ans[N];
int n, m, Q, rk[N], head[N << 2], dfn[N], et, v[N], tot, Z[N], as[N];
inline lll input() {
rr lll ans = 0, f = 1;
rr char c = getchar(); while (!isdigit(c))
f = (c == '-') ? -f : f, c = getchar(); while (isdigit(c))
ans = (ans << 3) + (ans << 1) + (c ^ 48), c = getchar(); return ans * f;
}
inline void print(lll ans) {
if (ans < 0)
putchar('-'), ans = -ans; if (ans > 9)
print(ans / 10); putchar(ans % 10 + 48);
}
inline lll dj(Point x, Point y) {//数量积
return x.x * y.x + x.y * y.y;
}
inline lll cj(Point x, Point y) {//向量积
return x.x * y.y - x.y * y.x;
}
inline void add(int x, int y) {
e[++et] = (node) {y, as[x]}, as[x] = et;
}
inline void update(int k, int l, int r, int x, int y, int z) {
if (l == x && r == y) {
while (K[k].size() > 1 && cj(a[z] - K[k][K[k].size() - 1], a[z] - K[k][K[k].size() - 2]) <= 0)
K[k].pop_back();//下凸壳,也就是向量积为顺时针时弹出队尾 K[k].push_back(a[z]);
return;
} rr int mid = (l + r) >> 1; if (y <= mid)
update(k << 1, l, mid, x, y, z);
else if (x > mid)
update(k << 1 | 1, mid + 1, r, x, y, z);
else
update(k << 1, l, mid, x, mid, z), update(k << 1 | 1, mid + 1, r, mid + 1, y, z);
}
inline lll kxb(lll k, Point x) {//实际答案
return k * x.x + x.y;
}
inline lll query(int k, int l, int r, int x, int z) {
rr int len = K[k].size();
rr lll ans = -2e18; if (len) {
while (head[k] < len - 1 && kxb(z, K[k][head[k]]) <= kxb(z, K[k][head[k] + 1]))
++head[k]; ans = kxb(z, K[k][head[k]]);
} if (l == r)
return ans; rr int mid = (l + r) >> 1; if (x <= mid)
return max(ans, query(k << 1, l, mid, x, z));
else
return max(ans, query(k << 1 | 1, mid + 1, r, x, z));
}
inline void dfs(int x) {
dfn[x] = ++tot; if (Z[x] > 0)
L[Z[x]].push_back(tot);//插入操作的开头 if (Z[x] < 0)
R[-Z[x]].push_back(tot - 1);//删除操作的结尾 for (rr int i = as[x]; i; i = e[i].next)
dfs(e[i].y); if (Z[x] > 0)
R[Z[x]].push_back(tot);//插入操作的结尾 if (Z[x] < 0)
L[-Z[x]].push_back(tot + 1);//删除操作的开头
}
bool cmp1(int x, int y) {//横坐标第一关键字
return a[x].x < a[y].x || (a[x].x == a[y].x && a[x].y < a[y].y);
}
bool cmp2(rec x, rec y) {//按斜率排序
return x.z < y.z;
}
signed main() {
freopen("travel.in", "r", stdin);
freopen("travel.out", "w", stdout);
n = input(), Q = input(),
L[1].push_back(1),
R[1].push_back(n), v[1] = 1;
a[m = 1] = (Point) {
0, -input()
};
//令第一个点为原点
for (rr int i = 2; i <= n; ++i) {
rr int opt = iut();
add(input() + 1, i);
rr int z = input() + 2; if (!v[z])
v[z] = ++m;//重新编号 if (opt == 1)
Z[i] = -v[z];//删除操作
else {
rr lll d = iut();
input(), input();
a[Z[i] = v[z]] = (Point) {
2 * d, -d *d - input()
};//添加点
}
} for (rr int i = 1; i <= m; ++i)
rk[i] = i; dfs(1), sort(rk + 1, rk + 1 + m, cmp1); for (rr int i = 1; i <= m; ++i) {
rr int len = L[rk[i]].size(); for (rr int j = 0; j < len; ++j) {
rr int Ll = L[rk[i]][j], Rr = R[rk[i]][j]; if (Ll <= Rr)
update(1, 1, n, Ll, Rr, rk[i]);
}
} for (rr int i = 1; i <= Q; ++i)
q[i] = (rec) {
dfn[input() + 1], input(), i
}; sort(q + 1, q + 1 + Q, cmp2); for (rr int i = 1; i <= Q; ++i)
ans[q[i].rk] = 1ll * q[i].z * q[i].z - query(1, 1, n, q[i].x, q[i].z); for (rr int i = 1; i <= Q; ++i)
print(ans[i]), putchar(10); return 0;
}

#线段树分治,凸壳#洛谷 5416 [CTSC2016]时空旅行的更多相关文章

  1. 线段树分治初步学习&洛谷P5227[AHOI2013]连通图

    线段树分治 其实思想说起来是比较简单的,我们把这个题里的所有操作(比如连边删边查询balabala)全部拍到一棵线段树上,然后对着整棵树dfs一下求解答案,顺便把操作做一下,回溯的时候撤销一下即可.虽 ...

  2. bzoj2402 陶陶的难题II 分数规划+树剖+线段树维护凸壳+二分

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2402 题解 看上去很像分数规划的模型.于是就二分吧.令 \[ \begin{align*}\f ...

  3. 李超线段树(segment[HEOI2013]-洛谷T4097)

    (neng了好久好久才糊弄懂得知识点...) 一.李超线段树 在线动态维护一个二维平面直角坐标系, 支持插入一条线段, 询问与直线x = x0相交的所有线段中,交点y的最大/小值 (若有多条线段符合条 ...

  4. 线段树板子1(洛谷P3372)

    传送 一道线段树板子(最简单的) 似乎之前在培训里写过线段树的样子?不记得了 何为线段树? 一般就是长成这样的树,树上的每个节点代表一个区间.线段树一般用于区间修改,区间查询的问题. 我们如何种写一棵 ...

  5. 洛谷.3733.[HAOI2017]八纵八横(线性基 线段树分治 bitset)

    LOJ 洛谷 最基本的思路同BZOJ2115 Xor,将图中所有环的异或和插入线性基,求一下线性基中数的异或最大值. 用bitset优化一下,暴力的复杂度是\(O(\frac{qmL^2}{w})\) ...

  6. Bzoj1018/洛谷P4246 [SHOI2008]堵塞的交通(线段树分治+并查集)

    题面 Bzoj 洛谷 题解 考虑用并查集维护图的连通性,接着用线段树分治对每个修改进行分治. 具体来说,就是用一个时间轴表示图的状态,用线段树维护,对于一条边,我们判断如果他的存在时间正好在这个区间内 ...

  7. 【洛谷4219】[BJOI2014]大融合(线段树分治)

    题目: 洛谷4219 分析: 很明显,查询的是删掉某条边后两端点所在连通块大小的乘积. 有加边和删边,想到LCT.但是我不会用LCT查连通块大小啊.果断弃了 有加边和删边,还跟连通性有关,于是开始yy ...

  8. LOJ 2312(洛谷 3733) 「HAOI2017」八纵八横——线段树分治+线性基+bitset

    题目:https://loj.ac/problem/2312 https://www.luogu.org/problemnew/show/P3733 原本以为要线段树分治+LCT,查了查发现环上的值直 ...

  9. 洛谷 P2147 [SDOI2008]洞穴勘测 (线段树分治)

    题目链接 题解 早就想写线段树分治的题了. 对于每条边,它存在于一段时间 我们按时间来搞 我们可把一条边看做一条线段 我们可以模拟线段树操作,不断分治下去 把覆盖\(l-r\)这段时间的线段筛选出来, ...

  10. 【洛谷4585】[FJOI2015] 火星商店问题(线段树分治)

    点此看题面 大致题意: 有\(n\)家店,每个商品有一个标价.每天,都可能有某家商店进货,也可能有某人去购物.一个人在购物时,会于编号在区间\([L_i,R_i]\)的商店里挑选一件进货\(d_i\) ...

随机推荐

  1. 常见的问题系列--- Swagger @ApiOperationSupport忽略失效的问题

    https://www.cnblogs.com/hujunwei/p/15853307.html

  2. linux7/8版本的docker-ce安装(2022/5/27亲测可行)

    centos7 # 先配阿里源 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup curl - ...

  3. 逆向实战31——xhs—xs算法分析

    前言 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 公众号链接 目标网站 aH ...

  4. 2024年,提升Windows开发和使用体验实践 - 小工具篇

    前言 本来是一篇文章的,不知不觉写成了系列. 其实开工那几天就已经写好了长文,这几天一忙就没连着发了. 本文介绍一些 Windows 上用的小工具. 美化/折腾/小工具 虽然这是在用 Windows ...

  5. 【架构师视角系列】QConfig配置中心系列之Server端(三)

    声明 原创文章,转载请标注.https://www.cnblogs.com/boycelee/p/17993697 <码头工人的一千零一夜>是一位专注于技术干货分享的博主,追随博主的文章, ...

  6. Server-side template injection 模板注入问题总结

    概念: 服务器模板注入(Server-side template injection) 攻击者能够使用本地的模板语法去注入一个恶意的payload,然后在服务器端执行该攻击,当与欧股直接输入数据到模板 ...

  7. viewui tree 自定义化(源码copy出来改动)#添加 获取selected 解决方案

    需求: 对树有title的点击效果,右侧有说明文字 和 按钮能点击,不能右键,系统用的壳已经有右键了. 出现的问题: viewui的tree有两年没更新了,对ui这块,是采取的render自定义,但是 ...

  8. idea dev 分支合并到 master 流程

    合并分支前要全部提交 包括config.js 要不merge时候很麻烦 1 切换到master分支 Checkout 2 Merge into Current 3 commit push 4 切换回d ...

  9. idea的安装和无限期试用

    十年前在笔者开发的时候一直使用的是eclipse软件,但后来所有的发现公司基本用的是idea,还得重新学习idea用法,所以准备在去新公司前,来学习使用idea吧 第一步:安装idea https:/ ...

  10. [https://atcoder.jp/contests/abc234/tasks/abc234_d Prefix K-th Max] 最小堆实现

    Problem Statement Given are a permutation P=(P_1,P_2,\ldots,P_N)P=(P1​,P2​,-,PN​) of (1,2,\ldots,N)( ...