传送门:http://uoj.ac/problem/198

【题解】

首先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】时空旅行的更多相关文章

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

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

  2. Luogu P5416 [CTSC2016]时空旅行

    第一次写线段树分治的题目,没想到是道这么毒的题233 首先发现题目里的\((x,y,z,c)\)就是在放屁,只有\((x,c)\)是有用的 因此我们可以把题意转化为,在某一个时间节点上,求出所有元素的 ...

  3. [CTSC2016]时空旅行

    description 题面 solution 线段树分治+斜率优化毒瘤题 题目可以简化为: 你要维护一个包含元素\((x,c)\)的集合 修改操作为从以前的一个版本更新,修改内容为添加或删除一个元素 ...

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

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

  5. CTSC2016时空旅行

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

  6. @loj - 2987@ 「CTSC2016」时空旅行

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 2045 年,人类的技术突飞猛进,已经找到了进行时空旅行的方法. ...

  7. 【CTSC2016】时空旅行

    链接 http://uoj.ac/problem/198 题解 首先要发现答案要我们求这个式子: \[ ans=min\bigl((x_i-x)^2+c_i\bigr) \] 显而易见的是这种时空嫁接 ...

  8. [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 ...

  9. 【UOJ #198】【CTSC 2016】时空旅行

    http://uoj.ac/problem/198 (先补一下以前的题解) 这道题5分暴力好写好调,链上部分分可以用可持久化线段树,每次旅行\(x\)值相同的可以用标记永久化线段树.我还听到某些神犇说 ...

随机推荐

  1. 「日常训练」 神、上帝以及老天爷 (HDU 2048)

    题意 数论中的错排问题.记错排为Dn" role="presentation">DnDn,求Dnn!" role="presentation&q ...

  2. 接口测试工具postman(二)创建新项目

    1.此次添加一个request,可以点击左上角的New的下拉选择Request,或者点击New弹出选项框点击Request 2.弹出新增request页面 3.添加请求的参数等 4.也可以直接添加新请 ...

  3. java.sql.Date java.sql.Time java.sql.Timestamp 之比较

    java.sql.Date,java.sql.Time和java.sql.Timestamp 三个都是java.util.Date的子类(包装类). java.sql.Date是java.util.D ...

  4. 转型、java基础之Java变量命名规范 (转载)

    向上转型:基类引用指向导出类(派生类)的对象(实例)向下转型:导出类的引用指向基类的对象(实例)  重点:向下转型只有将该引用的导出类的向上转型后向下转型,运行时才不会报错 Java是一种区分字母的大 ...

  5. bzoj1367 可并堆

    题面 参考:<左偏树的特点及运用--黄河源> 我们将这个数列划为很多个互不相交的区间,每一段区间内的 \(b\) 是相等的,即 \(b[l[i]]=b[l[i]+1]=...=b[r[i] ...

  6. Module安装

    利用pip3 install numpy,代表安装了数学模块 pip3 install -U numpy,代表升级数学模块 有的时候需要升级pip本身,如上所示,直接执行pip3 install -U ...

  7. SQLAlchemy 学习笔记(一):Engine 与 SQL 表达式语言

    个人笔记,如有错误烦请指正. SQLAlchemy 是一个用 Python 实现的 ORM (Object Relational Mapping)框架,它由多个组件构成,这些组件可以单独使用,也能独立 ...

  8. 项目启动报错: No naming context bound to this class loader

    发步项目到本地tomcat,启动后,一直包错:  警告: Failed to retrieve JNDI naming context for container [StandardEngine[Ca ...

  9. UVA 437 The Tower of Babylon(DAG上的动态规划)

    题目大意是根据所给的有无限多个的n种立方体,求其所堆砌成的塔最大高度. 方法1,建图求解,可以把问题转化成求DAG上的最长路问题 #include <cstdio> #include &l ...

  10. 解决hadoop no dataNode to stop问题

    错误原因: datanode的clusterID 和 namenode的 clusterID 不匹配. 解决办法: 1. 打开 hadoop/tmp/dfs/namenode/name/dir 配置对 ...