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\)值相同的可以用标记永久化线段树.我还听到某些神犇说 ...
随机推荐
- allegro导入网表过程中出现的错误信息
1. 找不到焊盘PAD,下面这句话的意思是器件封装找不到焊盘46.pad WARNING(SPMHNI-): Unable to load symbol ): Could not find padst ...
- python语句和语法
python语句和语法 python程序结构: 1.程序由模块构成. 2.模块包含语句. 3.语句包含表达式. 4.表达式建立并处理对象. python的语法实质上是有语句和表达式组成的.表达式处理对 ...
- Java笔试题-线程编程方面
Ja 线程编程方面 60.java中有几种方法可以实现一个线程?用什么关键字修饰同步方法?stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现R ...
- ES5新增数组方法(3):some
检查数组元素中是否有元素符合指定. // 数组中的元素部分满足指定条件返回true let arr = [1, 3, 5, 7, 9]; console.log(arr.some((value, in ...
- 数据库学习(二) case when then else end 的使用
case函数还用来统计数据的,参考资料:https://www.cnblogs.com/qlqwjy/p/7476533.html 这里我只是整理下工作中使用的到案例: 查询语句: SELECT t. ...
- AGV小车典型设计算法及应用
1. AGV小车的发展背景 在现代化工业的发展中,提倡高效,快速,可靠,提倡将人从简单的工作中解放出来.机器人逐渐替代了人出现在各个工作岗位上.机器人具有可编程.可协调作业和基于传感器控制等特点,自动 ...
- POJ 1149 PIGS(最大流)
Description Mirko works on a pig farm that consists of M locked pig-houses and Mirko can't unlock an ...
- 第5讲——cin处理字符输入
本来这一讲应该是while.for.if之类的,但是,我们可是学过C的男人,再浪费时间搞这个??? 还不如学点C++中的新知识. cin对象支持3种不同模式的单字符输入,其用户接口各不相同. 下面我们 ...
- lintcode-98-链表排序
98-链表排序 在 O(n log n) 时间复杂度和常数级的空间复杂度下给链表排序. 样例 给出 1->3->2->null,给它排序变成 1->2->3->nu ...
- 代码托管平台(Git)
1,可以说GitHub的出现完全颠覆了以往大家对代码托管网站的认识.GitHub不但是一个代码托管网站,更是一个程序员的SNS社区.GitHub真正 迷人的是它的创新能力与Geek精神,这些都是无法模 ...