uoj

description

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

有\(m\)次询问,每次给出一个\(x_0\),询问第\(s\)个集合中\((x-x_0)^2+c\)的最小值。

\(n,m\le5\times10^5\)

sol

把这个树形结构建出来,然后一个元素在树上存在的位置就是——一个连通块?

这样转化显得很蠢,实际上一个元素在树上存在的位置就是它第一次出现的点的子树中扣掉把它删除的点的子树。

这样子\(n\)种元素在树上的存在位置就是\(n\)个在\(\mbox{dfs}\)序上的连续区间。

观察答案式,因为长得很斜率优化,所以就把这\(n\)个区间丢到线段树上,在线段树的每个节点维护一个下凸壳。每个询问就在线段树的一条链上的每个线段树节点里边的凸壳上二分。复杂度\(O(n\log^2n)\)。

发现每次二分很蠢,可以直接在外部对询问的\(x\)排序,然后就不需要二分了。复杂度\(O(n\log n)\)。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
#define ll long long
ll gi(){
ll x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 5e5+5;
struct point{ll x,y;}p[N];
struct node{
int x,s,id;
bool operator < (const node &b) const
{return x<b.x;}
}q[N];
vector<int>S[N];vector<int>v[N<<2];
int n,m,nxt[N],head[N],val[N],dfn[N],low[N],tim,id[N],hd[N<<2];
ll X[N],C[N],ans[N];
void dfs(int u){
dfn[u]=++tim;S[val[u]].push_back(u);
for (int v=head[u];v;v=nxt[v]) dfs(v);
low[u]=tim;
}
bool cmp(int i,int j){return X[i]==X[j]?C[i]>C[j]:X[i]<X[j];}
void modify(int x,int l,int r,int ql,int qr,int i){
if (l>=ql&&r<=qr){
int sz=v[x].size();
while(sz>1&&(p[v[x][sz-1]].y-p[v[x][sz-2]].y)*(p[i].x-p[v[x][sz-1]].x)>=(p[i].y-p[v[x][sz-1]].y)*(p[v[x][sz-1]].x-p[v[x][sz-2]].x))--sz,v[x].pop_back();
v[x].push_back(i);return;
}
int mid=l+r>>1;
if (ql<=mid) modify(x<<1,l,mid,ql,qr,i);
if (qr>mid) modify(x<<1|1,mid+1,r,ql,qr,i);
}
ll query(int x,int l,int r,int s,int k){
ll res=1ll<<60;
if (int sz=v[x].size()){
while (hd[x]<sz-1&&p[v[x][hd[x]+1]].y-p[v[x][hd[x]]].y<1ll*k*(p[v[x][hd[x]+1]].x-p[v[x][hd[x]]].x)) ++hd[x];
res=p[v[x][hd[x]]].y-p[v[x][hd[x]]].x*k+1ll*k*k;
}
if (l==r) return res;int mid=l+r>>1;
if (s<=mid) return min(res,query(x<<1,l,mid,s,k));
else return min(res,query(x<<1|1,mid+1,r,s,k));
}
int main(){
n=gi();m=gi();C[1]=gi();val[1]=1;
for (int i=2;i<=n;++i)
if (!gi()){
int f=gi()+1,id=gi()+1;
X[id]=gi();gi(),gi();C[id]=gi();
nxt[i]=head[f];head[f]=i;val[i]=id;
}else{
int f=gi()+1,id=gi()+1;
nxt[i]=head[f];head[f]=i;val[i]=id;
}
dfs(1);
for (int i=1;i<=n;++i) id[i]=i;sort(id+1,id+n+1,cmp);
for (int i=1;i<=n;++i)
if (S[id[i]].size()){
p[i]=(point){2ll*X[id[i]],X[id[i]]*X[id[i]]+C[id[i]]};
int lst=dfn[S[id[i]][0]];
for (int j=1,sz=S[id[i]].size();j<sz;++j){
if (lst<dfn[S[id[i]][j]]) modify(1,1,n,lst,dfn[S[id[i]][j]]-1,i);
lst=low[S[id[i]][j]]+1;
}
if (lst<=low[S[id[i]][0]]) modify(1,1,n,lst,low[S[id[i]][0]],i);
}
for (int i=1,s,x;i<=m;++i) s=gi()+1,x=gi(),q[i]=(node){x,dfn[s],i};
sort(q+1,q+m+1);
for (int i=1;i<=m;++i) ans[q[i].id]=query(1,1,n,q[i].s,q[i].x);
for (int i=1;i<=m;++i) printf("%lld\n",ans[i]);
return 0;
}

[UOJ198][CTSC2016]时空旅行的更多相关文章

  1. Luogu P5416 [CTSC2016]时空旅行

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

  2. [CTSC2016]时空旅行

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

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

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

  4. CTSC2016时空旅行

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

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

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

  6. uoj198【CTSC2016】时空旅行

    传送门:http://uoj.ac/problem/198 [题解] 首先y.z是没有用的.. 然后式子就是w = (x0-xi)^2+ci的最小值,化出来可以变成一个直线的形式. 然后我们可以用线段 ...

  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. 20155305乔磊2016-2017-2《Java程序设计》第九周学习总结

    20155305 2016-2017-2 <Java程序设计>第九周学习总结 教材学习内容总结 JDBC入门 JDBC简介 1.JDBC是java联机数据库的标准规范,它定义了一组标准类与 ...

  2. zabbix监控路由器

    在路由器上添加团体名: snmp-server enable traps snmp-server community XXXX rw   1.使用Getif查看路由器端口信息 getif-2.31

  3. git如何在自动生成补丁时指定补丁名的起始编号

    答:使用选项--start-number,用法如下: git format-patch 1f43be --start-number=2 这样就可以生成起始编号为2的补丁名,类似0002-me.patc ...

  4. crontab 定时执行脚本出错,但手动执行脚本正常

    原因: crontab 没有去读环境变量,需要再脚本中手动引入环境变量,可以用source 也可以用export 写死环境变量. 为了定时监控Linux系统CPU.内存.负载的使用情况,写了个Shel ...

  5. Redis之持久化

    Redis 持久化 提供了多种不同级别的持久化方式:一种是RDB,另一种是AOF. RDB方式的持久化是通过快照(snapshotting)完成的,当符合一定条件时Redis会自动将内存中的所有数据进 ...

  6. 【转】集群/分布式环境下5种session处理策略

    转载至:http://blog.csdn.net/u010028869/article/details/50773174 在搭建完集群环境后,不得不考虑的一个问题就是用户访问产生的session如何处 ...

  7. jenkins svn源码管理小记

    之前对Jenkins管理SVN源码的逻辑不太清楚,简单研究了一下.对于一般的开发通常会有以下三个环境: 1.svn服务器 2.Jenkins服务器 3.开发服务器(部署测试版web应用或者其他应用) ...

  8. lua 删除table元素

    tab1 = { key1 = "val1", key2 = "val2", "val3" } for k, v in pairs(tab1 ...

  9. phpstorm 2017版代码提示功能开启解决方案

    安装好phpstorm 2017之后 发现代码高亮和函数自动提示都失效了 在phpstorm底部面板的信息提示处发现有一条系统消息: 12:04:18 Power save mode is on Co ...

  10. bzoj-4870-组合dp+矩阵幂

    4870: [Shoi2017]组合数问题 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 829  Solved: 446[Submit][Statu ...