【题目链接】

  • BZOJ
  • UOJ

【思路要点】

  • 我们发现所有星球的\(y\)和\(z\)坐标没有实质作用,问题仅和\(x\)和\(c\)有关。
  • 令询问给出的横坐标为\(qx\),那么一个属性为\((x,c)\)的星球被探索的代价为\((qx-x)^2+c=qx^2-2x*qx+(x^2+c)\)。显然\(qx^2\)只和询问有关,因此我们需要求\(-2x*qx+(x^2+c)\)的最小值,令\(k=-2x,b=x^2+c\),则要求的是\(k*qx+b\)的最小值。
  • 令\(k_1>k_2\),则\((k_1,b_1)\)优于\((k_2,b_2)\)的充要条件为\(k_1*qx+b_1≤k_2*qx+b_2\),也即\(-qx≥\frac{b_1-b_2}{k_1-k_2}\),容易看出,我们可以通过类似斜率优化的方式维护一个\((k,b)\)的下凸壳来快速找到最优解。
  • 在原树的DFS序上建立线段树,则每一个星球存在的时空是线段树上一段或多段区间,这样的区间的总数是\(O(N)\)的。在线段树定位到的每一个区间中加入\((k,b)\)并维护下凸壳,对于每个询问,查询包含询问点的所有区间的答案,取最小值。
  • 直接使用平衡树维护每个凸壳,询问时在凸壳上二分,时间复杂度为\(O(NLog^2N)\)(\(N\)、\(M\)同阶)。
  • 考虑离线操作,并将星球按照\(k\)排序,依次加入线段树,就可以用单调队列来维护凸壳了。
  • 同样地,我们离线询问,将询问按照\(-qx\)排序,依次询问,在线段树每个节点的询问就可以达到均摊\(O(1)\)的时间复杂度。
  • 时间复杂度\(O(NLogN)\)(\(N\)、\(M\)同阶)。

【代码】

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 500005;
const int MAXP = 7e6 + 5;
const long long INF = 1e18;
template <typename T> void chkmax(T &x, T y) {x = max(x, y); }
template <typename T> void chkmin(T &x, T y) {x = min(x, y); }
template <typename T> void read(T &x) {x = 0; int f = 1;char c = getchar();for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';x *= f;
}
template <typename T> void write(T x) {if (x < 0) x = -x, putchar('-');if (x > 9) write(x / 10);putchar(x % 10 + '0');
}
template <typename T> void writeln(T x) {write(x);puts("");
}
struct SegmentTree {struct Node {int lc, rc;int head, tail;} a[MAXN * 2];int n, root, size, tot;int nxt[MAXP], pre[MAXP];long long k[MAXP], b[MAXP];void build(int &root, int l, int r) {root = ++size;if (l == r) return;int mid = (l + r) / 2;build(a[root].lc, l, mid);build(a[root].rc, mid + 1, r);}void init(int x) {n = x;root = size = 0;build(root, 1, n);}void insert(int root, int l, int r, int ql, int qr, long long vk, long long vb) {if (l == ql && r == qr) {if (a[root].tail) {if (k[a[root].tail] == vk) {if (vb >= b[a[root].tail]) return;else {a[root].tail = pre[a[root].tail];nxt[a[root].tail] = 0;if (a[root].tail == 0) a[root].head = 0;}}while (a[root].tail != a[root].head) {int tmp = a[root].tail;int tnp = pre[tmp];if ((vk - k[tnp]) * (b[tmp] - b[tnp]) >= (k[tmp] - k[tnp]) * (vb - b[tnp])) {a[root].tail = pre[a[root].tail];nxt[a[root].tail] = 0;} else break;}if (a[root].tail) {nxt[a[root].tail] = ++tot;pre[tot] = a[root].tail;k[tot] = vk, b[tot] = vb;a[root].tail = tot;} else {a[root].head = a[root].tail = ++tot;k[tot] = vk, b[tot] = vb;}} else {a[root].head = a[root].tail = ++tot;k[tot] = vk, b[tot] = vb;}return;}int mid = (l + r) / 2;if (mid >= ql) insert(a[root].lc, l, mid, ql, min(mid, qr), vk, vb);if (mid + 1 <= qr) insert(a[root].rc, mid + 1, r, max(mid + 1, ql), qr, vk, vb);}void insert(int l, int r, long long vk, long long vb) {insert(root, 1, n, l, r, vk, vb);}long long query(int root, int l, int r, int pos, long long x) {long long ans = INF;if (a[root].head) {ans = k[a[root].head] * x + b[a[root].head];while (a[root].head != a[root].tail) {int tmp = nxt[a[root].head];long long tnp = k[tmp] * x + b[tmp];if (tnp <= ans) {ans = tnp;a[root].head = nxt[a[root].head];pre[a[root].head] = 0;} else break;}}if (l == r) return ans;int mid = (l + r) / 2;if (mid >= pos) chkmin(ans, query(a[root].lc, l, mid, pos, x));else chkmin(ans, query(a[root].rc, mid + 1, r, pos, x));return ans;}long long query(int pos, long long x) {return query(root, 1, n, pos, x);}
} ST;
vector <int> a[MAXN], del[MAXN];
int n, m, fa[MAXN], ins[MAXN];
int timer, dfn[MAXN], rit[MAXN];
long long k[MAXN], b[MAXN];
int to[MAXN]; long long x[MAXN], ans[MAXN];
void dfs(int pos) {dfn[pos] = ++timer;for (unsigned i = 0; i < a[pos].size(); i++)dfs(a[pos][i]);rit[pos] = timer;
}
bool cmp(int x, int y) {return k[x] < k[y];
}
bool cnp(int x, int y) {return dfn[x] < dfn[y];
}
bool mmp(int a, int b) {return x[a] > x[b];
}
int main() {read(n), read(m), read(b[1]); ins[1] = 1;for (int i = 2; i <= n; i++) {int opt; read(opt);read(fa[i]), fa[i]++;a[fa[i]].push_back(i);int id; read(id), id++;if (opt == 0) {ins[id] = i;long long x, y, z, c;read(x), read(y), read(z), read(c);k[id] = -2 * x, b[id] = c + x * x;} else del[id].push_back(i);}dfs(1);static int pos[MAXN];for (int i = 1; i <= n; i++)pos[i] = i;sort(pos + 1, pos + n + 1, cmp);ST.init(n);for (int i = 1; i <= n; i++) {int tmp = pos[i];if (ins[tmp] == 0) continue;sort(del[tmp].begin(), del[tmp].end(), cnp);int lft = dfn[ins[tmp]];for (unsigned i = 0; i < del[tmp].size(); i++) {int tnp = del[tmp][i];if (dfn[tnp] != lft) ST.insert(lft, dfn[tnp] - 1, k[tmp], b[tmp]);lft = rit[tnp] + 1; }if (lft <= rit[ins[tmp]]) ST.insert(lft, rit[ins[tmp]], k[tmp], b[tmp]);}for (int i = 1; i <= m; i++) {read(to[i]), read(x[i]), to[i]++;pos[i] = i;}sort(pos + 1, pos + m + 1, mmp);for (int i = 1; i <= m; i++) {int tmp = pos[i];ans[tmp] = ST.query(dfn[to[tmp]], x[tmp]) + x[tmp] * x[tmp];}for (int i = 1; i <= m; i++)printf("%lld\n", ans[i]);return 0;
}

【BZOJ5077】【UOJ198】【CTSC2016】时空旅行相关推荐

  1. [UOJ198][CTSC2016]时空旅行

    uoj description 你要维护若干个集合,每个集合都是有一个编号比他小的集合扩展而来,扩展内容为加入一个新的元素\((x,c)\)或者删除一个已有元素.集合的扩展关系之间构成一个树形结构. ...

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

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

  3. bzoj5077: [Ctsc2016]时空旅行【线段树+凸包】

    Description 2045年,人类的技术突飞猛进,已经找到了进行时空旅行的方法.小R得到了一台时空旅行仪,他想用它调查不同 时空中人类的发展状况.根据平行时空理论,宇宙中存在着很多独立的时空,每 ...

  4. BZOJ5077: [Ctsc2016]时空旅行(线段树+凸包)

    传送门 题解: 首先答案为min(x−xi)2+cimin(x−xi)2+ci\min {(x-x_i)^2+c_i},移项得x2−2xix+x2i+cx2−2xix+xi2+cx^2 -2x_ix+ ...

  5. [CTSC2016]时空旅行(斜率优化+线段树分治)

    洛谷题目传送门 解题思路 首先发现只有xxx和ccc是有用的 这些时空构成了一棵树,我们实际上要找一个点iii,满足对于给出的XXX min((X−xi)2+ci)min((X-x_i)^2+c_i) ...

  6. [CTSC2016]时空旅行

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

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

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

  8. CTSC2016时空旅行

    当时看这道题AC的人数比较多,就开了这道题. 很容易发现是这是一个有关凸包的题. 然后不知道怎么维护凸包,一直在想cdq,感觉复杂度不行,于是被这玩意难住了-- 幸好有亲学长yyh造福人类的题解:ht ...

  9. Luogu P5416 [CTSC2016]时空旅行

    题目 简化题意:你需要维护\(n\)个集合,集合元素为二元组\((x,v)\).集合\(i\)的产生方式是以某个原有集合\(p_i\)为样本,扩展或删除一个元素后得到新集合.有\(q\)次询问,每次给 ...

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

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

最新文章

  1. 明晚直播丨上海名师王召强:高考大变脸后,中小学语文怎么学?
  2. PowerBI随笔(2)-分组依据进行分组汇总
  3. 前端学习(1715):前端系列javascript之页面配置
  4. 织梦 详情页 php,织梦DEDECMS列表页与详情页调用图集多张图片的方法
  5. 解析网上的XML文件
  6. git新建空白文件没有生效
  7. 国际旅游管理专业跨专业考计算机,第二年跨校跨专业考旅游管理公费成功,一点经验给大家...
  8. 零基础带你学习MySQL—分页查询(十八)
  9. swiper 上滑触发_新知 | 为何红酒杯壁挂“眼泪”,骑自行车不会倒,冰面那么滑?...
  10. 从客户端中检测到有潜在危险的 Request.Form 值。
  11. 结构化随机森林 代码说明
  12. 关于Enterprise library logging中一个没搞明白的东西,希望有大大们进来帮忙释疑一下, THKS...
  13. 百度地图ModuleNotFoundError: No module named ‘aip‘
  14. 【笔记】Oracle触发器,根据另外一张表是否存在此记录,来判断是否更新
  15. 点云八个方向极值点获取
  16. 吴晓波:预见2021(跨年演讲 —— 08 超级城市大赛鸣枪)
  17. 女友老爸开了中介公司让我抽空搞开发个租房App,像贝壳一样就行.....
  18. 3D游戏之父--John Carmack连载系列(四)
  19. RRC连接、RL、RB、RAB的本质是什么?
  20. JAVA使用barcode4j生成条形码和二维码图片以及带logo的二维码,验证码图片

热门文章

  1. 菩提本无树,明镜亦非台
  2. JavaScript面向对象
  3. 防火墙一个系统加固的例子
  4. echarts 省级地图下钻到市demo
  5. Spring Cloud 是面面观
  6. 服务器维护灵魂兽刷新吗,抓灵魂兽的各种辛酸,魔兽世界猎人当年抓灵魂兽用过的黑科技漫谈...
  7. 量化分析入门5:列表和收盘价的移动平均的示例
  8. U盘文件格式化后怎么快速恢复
  9. 和Leo一起做爱线段树的好孩子HDU5238 Calculator
  10. Julia文件和文件夹相关基础函数01