uoj198【CTSC2016】时空旅行
【题解】
首先y、z是没有用的。。
然后式子就是w = (x0-xi)^2+ci的最小值,化出来可以变成一个直线的形式。
然后我们可以用线段树维护dfs序上的每个点。
每个点维护经过这个点的所有直线(标记永久化),也就是维护上凸壳。
然后我们把询问按照x排序,每次决策点只会后移。所以复杂度就有保证啦!
真**难写
还有一个十分有趣的事实啊
我用一个号交完ac在另一个号再交就RE了啊。。。
不管了反正过了
# include <vector>
# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h> using namespace std; typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + ;
const int mod = 1e9+; # define RG register
# define ST static int n, q, s[M], ps[M];
ll c0, ans[M];
vector<int> b[M];
struct planet {
int x; ll c;
planet() {}
planet(int x, ll c) : x(x), c(c) {}
friend bool operator < (planet a, planet b) {
return a.x<b.x;
}
}p[M]; struct line {
ll k, b;
line() {}
line(ll k, ll b) : k(k), b(b) {}
inline ll set(int x) {
return k*(ll)x+b;
}
}; struct quest {
int s, x0, id;
quest() {}
quest(int s, int x0, int id) : s(s), x0(x0), id(id) {}
friend bool operator < (quest a, quest b) {
return a.x0<b.x0;
}
}qu[M]; int head[M], nxt[M], to[M], tot, in[M], out[M], DFN;
inline void add(int u, int v) {
++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
} inline void dfs(int x) {
in[x] = ++DFN;
for (int i=head[x]; i; i=nxt[i]) dfs(to[i]);
out[x] = DFN;
} inline bool cmp(int x, int y) {
return p[x].x<p[y].x;
} inline bool cmp_b(int x, int y) {
return in[x] < in[y];
} namespace SMT {
const int M = 2e6 + ;
vector<line> w[M];
int lst[M]; inline bool canout(line a, line b, line c) {
if(b.k == c.k) return b.b >= c.b;
return 1.0*(b.b-a.b)*(a.k-c.k) > 1.0*(c.b-a.b) * (a.k-b.k);
} inline void change(int x, int l, int r, int L, int R, line add) {
if(L <= l && r <= R) {
if(w[x].size()) {
while(w[x].size() > && canout(w[x][w[x].size()-], w[x][w[x].size()-], add)) w[x].pop_back();
w[x].push_back(add);
} else w[x].push_back(add);
return ;
}
int mid = l+r>>;
if(L <= mid) change(x<<, l, mid, L, R, add);
if(R > mid) change(x<<|, mid+, r, L, R, add);
} inline ll query(int x, int l, int r, int pos, int x0) {
while(lst[x]+ < w[x].size() && w[x][lst[x]].set(x0) > w[x][lst[x]+].set(x0)) ++lst[x];
ll cur = (w[x].size() ? w[x][lst[x]].set(x0) : 1e18);
if(l == r) return cur;
int mid = l+r>>;
if(pos <= mid) return min(cur, query(x<<, l, mid, pos, x0));
else return min(cur, query(x<<|, mid+, r, pos, x0));
} inline void change(int L, int R, line add) {
if(L>R) return;
change(, , DFN, L, R, add);
}
inline ll query(int pos, int x0) {
return query(, , DFN, pos, x0);
}
} int main() {
scanf("%d%d%lld", &n, &q, &c0);
for (int i=, op, fr, id, x, c; i<n; ++i) {
ps[i] = i;
scanf("%d%d%d", &op, &fr, &id);
if(op == ) {
scanf("%d%*d%*d%lld", &x, &c);
s[id] = i;
p[id] = planet(x, c);
} else b[id].push_back(i);
add(fr, i);
}
dfs();
sort(ps+, ps+n, cmp);
for (int i=, t; i<n; ++i) {
if(s[ps[i]]) {
int id = ps[i], se = s[id];
line L = line(-2ll*p[id].x, 1ll*p[id].x*p[id].x+p[id].c);
if(b[id].size()) {
sort(b[id].begin(), b[id].end(), cmp_b);
t = b[id].size();
SMT::change(in[se], in[b[id][]]-, L);
SMT::change(out[b[id][t-]]+, out[se], L);
for (int j=; j<t; ++j)
SMT::change(out[b[id][j-]]+, in[b[id][j]]-, L);
} else SMT::change(in[se], out[se], L);
}
}
for (int i=; i<=q; ++i) {
scanf("%d%d", &qu[i].s, &qu[i].x0);
qu[i].id=i;
}
sort(qu+, qu+q+);
for (int i=; i<=q; ++i)
ans[qu[i].id] = 1ll * qu[i].x0 * qu[i].x0 + min(c0, SMT::query(in[qu[i].s], qu[i].x0));
for (int i=; i<=q; ++i) printf("%lld\n", ans[i]);
return ;
}
uoj198【CTSC2016】时空旅行的更多相关文章
- [UOJ198][CTSC2016]时空旅行
uoj description 你要维护若干个集合,每个集合都是有一个编号比他小的集合扩展而来,扩展内容为加入一个新的元素\((x,c)\)或者删除一个已有元素.集合的扩展关系之间构成一个树形结构. ...
- Luogu P5416 [CTSC2016]时空旅行
第一次写线段树分治的题目,没想到是道这么毒的题233 首先发现题目里的\((x,y,z,c)\)就是在放屁,只有\((x,c)\)是有用的 因此我们可以把题意转化为,在某一个时间节点上,求出所有元素的 ...
- [CTSC2016]时空旅行
description 题面 solution 线段树分治+斜率优化毒瘤题 题目可以简化为: 你要维护一个包含元素\((x,c)\)的集合 修改操作为从以前的一个版本更新,修改内容为添加或删除一个元素 ...
- [CTSC2016]时空旅行(线段树+凸包)
应该是比较套路的,但是要A掉仍然不容易. 下面理一下思路,思路清楚了也就不难写出来了. 0.显然y,z坐标是搞笑的,忽略即可. 1.如果x不变,那么直接set即可解决. 2.考虑一个空间和询问x0,通 ...
- CTSC2016时空旅行
当时看这道题AC的人数比较多,就开了这道题. 很容易发现是这是一个有关凸包的题. 然后不知道怎么维护凸包,一直在想cdq,感觉复杂度不行,于是被这玩意难住了…… 幸好有亲学长yyh造福人类的题解:ht ...
- @loj - 2987@ 「CTSC2016」时空旅行
目录 @description@ @solution@ @accepted code@ @details@ @description@ 2045 年,人类的技术突飞猛进,已经找到了进行时空旅行的方法. ...
- 【CTSC2016】时空旅行
链接 http://uoj.ac/problem/198 题解 首先要发现答案要我们求这个式子: \[ ans=min\bigl((x_i-x)^2+c_i\bigr) \] 显而易见的是这种时空嫁接 ...
- [UOJ198]时空旅行
看懂题目就知道$y,z$是没用的,这题相当于是给一堆$(x_i,c_i)$和询问$x_q$,要求$(x_q-x_i)^2+c_i$的最大值 先把这个式子拆开:$-2x_ix_q+x_i^2+c_i+x ...
- 【UOJ #198】【CTSC 2016】时空旅行
http://uoj.ac/problem/198 (先补一下以前的题解) 这道题5分暴力好写好调,链上部分分可以用可持久化线段树,每次旅行\(x\)值相同的可以用标记永久化线段树.我还听到某些神犇说 ...
随机推荐
- html5学得好不好,看掌握多少标签
html5学得好不好,看掌握多少标签 已回复 会员ID:wi701329 保密 62岁 时间:2016-06-28 06:52:49 html5你了解了多少?如果你还是入门阶段的话,或者还是一知半解的 ...
- 「Haskell 学习」一 环境与大致了解
感谢<Real World Haskell>在网上的免费发布,可以白嫖学Haskell这个久闻大名的函数式编程语言了. 本文运行于openSUSE Tumbleweed下,运行相关命令时留 ...
- ES6 语法糖
重新认识ES6中的语法糖:https://segmentfault.com/a/1190000010159725
- 序列化---fastjson使用
该文章主要介绍com.alibaba.fastjson的使用. 首先创建maven工程,导入fastjson.挑个热度高的版本就好了. 首先考虑下,我们通常什么时候会使用序列化和反序列化: 1.将ja ...
- docker简单命令
查看镜像 docker images 查看正在使用的容器 docker ps -a 进入容器控制台 docker exec -it 容器ID bash 启动镜像 docker run -it -d.. ...
- python基础训练营03——字典、集合、判断、循环
一.字典dict: 相比列表list而言,列表list像一本书,如果要查书中的某一个内容,需要把书从前往后翻一遍,直到找到想要获取的东西:而字典dict,就像现实中的字典一样,通过查找特定的字或者词( ...
- python之pyquery库
如果熟悉jquery,那么使用pyquery进行网页信息提取将会是非常方便的,因为语法都是一样的 1.字符串初始化 2.url和文件初始化 3.CSS选择器 4.子元素 5.父元素 6.兄弟节点 7. ...
- Activiti工作流(一)——Activiti Diagram
工作流解决在多个参与者之间按照某种预定义的规则传递文档.信息或任务的过程自动进行,从而实现某个预期的业务目标,或者促使此目标的实现. 使用Eclipse开发,需要安排工作流插件,详情见下面. Name ...
- 【PHP】- 魔术常量
PHP 向它运行的任何脚本提供了大量的预定义常量.不过很多常量都是由不同的扩展库定义的,只有在加载了这些扩展库时才会出现,或者动态加载后,或者在编译时已经包括进去了.有八个魔术常量它们的值随着它们在代 ...
- SQL Server Profiler的简单使用,方便查找和发现SQL执行的效率和语句问题
1 打开Server Profiler 2 去掉不必要的干扰,数据库的连接和断开之类的 3. 选择“显示所有列”,之后在列表中,勾选“DatabaseName”项. 4设置筛选器,这里设置只是过滤数据 ...