[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_q^2$,那么询问就是求一堆直线$y=-2x_ix+x_i^2+c_i$在$x=x_q$处的最小值,维护坐标轴底端的上凸壳即可
再看题目中关于“时空”的限制,其实就是给一棵树,某一些点会有标记表示以这个点为根的子树内有/没有一条直线,我们用dfs序在线段树上覆盖对应区间并预处理出每个线段树节点的凸壳即可
把询问按$x$排序,那么我们查询时就可以在线段树上利用单调性做到$O(m\log_2n+n)$
总时间复杂度$O(n\log_2^2n+m\log_2n)$
代码准确度++
#include<stdio.h> #include<algorithm> #include<vector> using namespace std; typedef long long ll; typedef double du; const du eps=1e-8; const ll inf=9223372036854775807ll; int h[500010],nex[500010],to[500010],in[500010],ou[500010],M; void add(int a,int b){ M++; to[M]=b; nex[M]=h[a]; h[a]=M; } void dfs(int x){ M++; in[x]=M; for(int i=h[x];i;i=nex[i])dfs(to[i]); ou[x]=M; } ll c[500010],x[500010]; int at[500010]; vector<int>pl[2000010],del[500010],tmp; vector<int>::iterator it; bool cmp1(int x,int y){return in[x]<in[y];} bool cmp2(int i,int j){return(x[i]==x[j])?x[i]*x[i]+c[i]>x[j]*x[j]+c[j]:(x[i]<x[j]);} void modify(int L,int R,int v,int l,int r,int x){ if(L<=l&&r<=R)return pl[x].push_back(v); int mid=(l+r)>>1; if(L<=mid)modify(L,R,v,l,mid,x<<1); if(mid<R)modify(L,R,v,mid+1,r,x<<1|1); } du ins(int i,int j){return(x[i]*x[i]+c[i]-x[j]*x[j]-c[j])/((x[i]-x[j])*2.);} bool leq(du x,du y){return x-y<eps;} void dfs(int l,int r,int u){ sort(pl[u].begin(),pl[u].end(),cmp2); tmp.clear(); for(it=pl[u].begin();it!=pl[u].end();it++){ while(!tmp.empty()){ if(x[*tmp.rbegin()]==x[*it]){ tmp.pop_back(); continue; } if(tmp.size()==1)break; if(leq(ins(*tmp.rbegin(),*it),ins(tmp[tmp.size()-2],*it))) tmp.pop_back(); else break; } tmp.push_back(*it); } pl[u]=tmp; if(l==r)return; int mid=(l+r)>>1; dfs(l,mid,u<<1); dfs(mid+1,r,u<<1|1); } struct ask{ int s,id; ll x; }q[500010]; ll ans[500010]; int head[2000010]; bool cmp3(ask a,ask b){return a.x<b.x;} ll calc(int i,ll x0){return-2ll*x[i]*x0+x[i]*x[i]+c[i];} ll query(int u,ll x0,int l,int r,int x){ ll ans=inf; if(!pl[x].empty()){ while(head[x]<(int)pl[x].size()-1&&leq(ins(pl[x][head[x]],pl[x][head[x]+1]),x0))head[x]++; ans=min(ans,calc(pl[x][head[x]],x0)); } if(l==r)return ans; int mid=(l+r)>>1; if(u<=mid) ans=min(ans,query(u,x0,l,mid,x<<1)); else ans=min(ans,query(u,x0,mid+1,r,x<<1|1)); return ans; } int main(){ int n,m,i,op,fr,id,y,z; scanf("%d%d%lld",&n,&m,c+1); at[1]=1; for(i=2;i<=n;i++){ scanf("%d%d%d",&op,&fr,&id); fr++; id++; add(fr,i); if(op==0){ scanf("%lld%d%d%lld",x+id,&y,&z,c+id); at[id]=i; }else del[id].push_back(i); } M=0; dfs(1); for(i=1;i<=n;i++){ if(at[i]){ sort(del[i].begin(),del[i].end(),cmp1); y=in[at[i]]; for(it=del[i].begin();it!=del[i].end();it++){ if(y<in[*it])modify(y,in[*it]-1,i,1,n,1); y=ou[*it]+1; } if(y<=ou[at[i]])modify(y,ou[at[i]],i,1,n,1); } } dfs(1,n,1); for(i=1;i<=m;i++){ scanf("%d%lld",&q[i].s,&q[i].x); q[i].s++; q[i].id=i; } sort(q+1,q+m+1,cmp3); for(i=1;i<=m;i++)ans[q[i].id]=query(in[q[i].s],q[i].x,1,n,1)+q[i].x*q[i].x; for(i=1;i<=m;i++)printf("%lld\n",ans[i]); }
[UOJ198]时空旅行的更多相关文章
- @loj - 2987@ 「CTSC2016」时空旅行
目录 @description@ @solution@ @accepted code@ @details@ @description@ 2045 年,人类的技术突飞猛进,已经找到了进行时空旅行的方法. ...
- [UOJ198][CTSC2016]时空旅行
uoj description 你要维护若干个集合,每个集合都是有一个编号比他小的集合扩展而来,扩展内容为加入一个新的元素\((x,c)\)或者删除一个已有元素.集合的扩展关系之间构成一个树形结构. ...
- uoj198【CTSC2016】时空旅行
传送门:http://uoj.ac/problem/198 [题解] 首先y.z是没有用的.. 然后式子就是w = (x0-xi)^2+ci的最小值,化出来可以变成一个直线的形式. 然后我们可以用线段 ...
- 【UOJ #198】【CTSC 2016】时空旅行
http://uoj.ac/problem/198 (先补一下以前的题解) 这道题5分暴力好写好调,链上部分分可以用可持久化线段树,每次旅行\(x\)值相同的可以用标记永久化线段树.我还听到某些神犇说 ...
- 【CTSC2016】时空旅行
链接 http://uoj.ac/problem/198 题解 首先要发现答案要我们求这个式子: \[ ans=min\bigl((x_i-x)^2+c_i\bigr) \] 显而易见的是这种时空嫁接 ...
- 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 ...
随机推荐
- 停止ambari上服务的顺序
Before performing any upgrades or uninstalling software, stop all of the Hadoop services in the foll ...
- Elasticsearch 5.2.1Cluster 搭建
1.安装java cd ~ wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fw ...
- Sencha Touch2 -- 11.1:定义具有关联关系的模型
在Sencha Touch2.0中,可以定义不同模型之间的关联关系.例如,在开发博客网站的时候,可以首先定义用户(User)模型,然后为用户定义文章(Article)模型.一个用户可以发表多篇文章,因 ...
- Struts2 利用拦截器 interceptor 控制登陆和访问权限
最近学习了Struts2的登录和权限控制用到的是拦截器,需要在struts.xml中配置,每个action都默认的继承defaultStack,如果你用了别的拦截器,还需要手动引入defaultSta ...
- HASHMAP原理解析,不错的文章
http://blog.csdn.net/vking_wang/article/details/14166593
- 【uva11468-Substring】AC自动机+dp
http://acm.hust.edu.cn/vjudge/problem/31655 题意:给定k个模板串,n个字符以及选择它的概率pro[i],要构造一个长度问L的字符串s,问s不包含任意一个模板 ...
- 【洛谷 P1364】医院设置(树的重心)
树的重心的定义: 树若以某点为根,使得该树最大子树的结点数最小,那么这个点则为该树的重心,一棵树可能有多个重心. 树的重心的性质: 1.树上所有的点到树的重心的距离之和是最短的,如果有多个重心,那么总 ...
- POJ 2395 Out of Hay (prim)
题目链接 Description The cows have run out of hay, a horrible event that must be remedied immediately. B ...
- Golang在视频直播平台的高性能实践(含PPT下载)
熊猫 TV 是一家视频直播平台,先介绍下我们系统运行的环境,下面这 6 大服务只是我们几十个服务中的一部分,由于并发量与重要性比较高,所以成为 golang 小试牛刀的首批高性能高并发服务. 把大服务 ...
- 网络知识===cookie 、session、JSESSIONID的区别
cookie .session ? 让我们用几个例子来描述一下cookie和session机制之间的区别与联系.笔者曾经常去的一家咖啡店有喝5杯咖啡免费赠一杯咖啡的优惠,然而一次性消费5杯咖啡的机会微 ...