【CTSC2016】时空旅行
链接
题解
首先要发现答案要我们求这个式子:
\]
显而易见的是这种时空嫁接的关系会形成一棵树。但是我们并不能像\(NOI2014\)购票那样直接在树上维护一条链的栈,因为每个点代表的既有可能是加入一个点,又有可能是删除一个点。
考虑每个点的存在时间都是一些连续区间,所以就可以在欧拉序或者\(dfs\)序上分治了。
至于询问的方式,我们可以先把线段树上的每个节点把凸包维护出来,然后用标记永久化的思想进行查询。
如果空间利用的不当会\(MLE\),可以考虑先用栈做凸包,然后再扔进\(vector\)里做查询用,这样可以省空间。
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<algorithm>
#include<cstring>
#define ls tr[cnt].l
#define rs tr[cnt].r
#define N 500009
#define inf 1e16
using namespace std;
typedef long long ll;
int tot,head[N],num,val[N],n,sta[N<<1],root,dfn[N],_tag[N],m,totp;
ll ans;
ll c[N];
int pos[N];
struct edge{int n,to;}e[N];
inline void add(int u,int v){e[++tot].n=head[u];e[tot].to=v;head[u]=tot;}
struct seg{int l,r;}tr[N<<1];
struct node{
int x;ll y;
inline node operator +(const node &b)const{return node{1ll*x+b.x,y+b.y};}
inline node operator -(const node &b)const{return node{1ll*x-b.x,y-b.y};}
inline ll operator *(const node &b)const{return 1ll*x*b.y-y*b.x;}
inline bool operator <(const node &b)const{if(x!=b.x)return x<b.x;else return y<b.y;}
}st[N];
vector<node>vec[N<<1];
inline ll rd(){
ll x=0;char c=getchar();bool f=0;
while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
return f?-x:x;
}
inline double getk(node x,node y){return (double)(y.y-x.y)/(y.x-x.x);}
void build(int &cnt,int l,int r){
cnt=++totp;
if(l==r)return;
int mid=(l+r)>>1;
build(ls,l,mid);build(rs,mid+1,r);
}
inline void _query(int cnt,ll x){
if(vec[cnt].empty())return;
int l=0,r=vec[cnt].size()-2,now=r+1;
while(l<=r){
int mid=(l+r)>>1;
if(getk(vec[cnt][mid+1],vec[cnt][mid])>=x)now=mid,r=mid-1;
else l=mid+1;
}
ans=min(ans,vec[cnt][now].y-1ll*vec[cnt][now].x*x+x*x);
}
void upd(int cnt,int l,int r,int L,int R,int x){
// if(cnt==1)cout<<x<<" "<<L<<" "<<R<<endl;
if(l>=L&&r<=R){vec[cnt].push_back(node{1ll*pos[x]*2,1ll*pos[x]*pos[x]+c[x]});return;}
int mid=(l+r)>>1;
if(mid>=L)upd(ls,l,mid,L,R,x);
if(mid<R)upd(rs,mid+1,r,L,R,x);
}
void solve(int cnt,int l,int r){
sort(vec[cnt].begin(),vec[cnt].end());
int tp=0;
for(int i=0;i<vec[cnt].size();++i){
node xx=vec[cnt][i];
if(tp&&xx.x==st[tp].x)continue;
while(tp>1&&(xx-st[tp-1])*(st[tp]-st[tp-1])>=0)tp--;
st[++tp]=xx;
}
vec[cnt].clear();
for(int i=1;i<=tp;++i)vec[cnt].push_back(st[i]);
if(l==r)return;
int mid=(l+r)>>1;
solve(tr[cnt].l,l,mid);solve(tr[cnt].r,mid+1,r);
}
void query(int cnt,int l,int r,int x,int y){
_query(cnt,y);
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)query(ls,l,mid,x,y);
else query(rs,mid+1,r,x,y);
}
void work(int tim,int now,int tag){
if(tag==1){
if(val[now]>=0)sta[val[now]]=tim;
else upd(root,1,n,sta[-val[now]],tim-1,-val[now]),sta[-val[now]]=0;
}
else{
if(val[now]<0)sta[-val[now]]=tim+1;
else upd(root,1,n,sta[val[now]],tim,val[now]),sta[val[now]]=0;
}
}
void dfs(int u){
dfn[u]=++dfn[0];
work(dfn[0],u,1);
_tag[u]=dfn[0];
for(int i=head[u];i;i=e[i].n)dfs(e[i].to);
work(dfn[0],u,-1);
}
int main(){
//freopen("1.in","r",stdin);
n=rd();m=rd();c[0]=rd();
ll opt,f,id,x,y,z;
for(int i=1;i<n;++i){
opt=rd();f=rd();id=rd();add(f,i);
if(!opt){
pos[id]=rd();y=rd();z=rd();c[id]=rd();
val[i]=id;
}
else val[i]=-id;
}
build(root,1,n);
dfs(0);
for(int i=0;i<=n;++i)
if(sta[i])upd(root,1,n,sta[i],n,i);
solve(root,1,n);
int s;
for(int i=1;i<=m;++i){
s=rd();x=rd();ans=inf;
query(root,1,n,_tag[s],x);
printf("%lld\n",ans);
}
return 0;
}
【CTSC2016】时空旅行的更多相关文章
- Luogu P5416 [CTSC2016]时空旅行
第一次写线段树分治的题目,没想到是道这么毒的题233 首先发现题目里的\((x,y,z,c)\)就是在放屁,只有\((x,c)\)是有用的 因此我们可以把题意转化为,在某一个时间节点上,求出所有元素的 ...
- [UOJ198][CTSC2016]时空旅行
uoj description 你要维护若干个集合,每个集合都是有一个编号比他小的集合扩展而来,扩展内容为加入一个新的元素\((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 年,人类的技术突飞猛进,已经找到了进行时空旅行的方法. ...
- 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\)值相同的可以用标记永久化线段树.我还听到某些神犇说 ...
- [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 ...
随机推荐
- dubbo-源码分析Provider
Dubbo provider启动原理: 当我们的dubbo启动我们的spring容器时spring 初始化容器的时候会查找META-INF/spring.handles文件查找对应的Namespace ...
- nginx系列7:处理HTTP请求的11个阶段
处理HTTP请求的11个阶段 如下图: 序号 阶段 指令 备注 1 POST_READ realip 获取客户端真实IP 2 SERVER_REWRITE rewrite 3 FIND_CONFIG ...
- PHP+nginx 启动后访问超时
场景 在Windows上, nginx配置并启动后, 访问报504超时 解决 很尴尬, php-cgi没启动 php-cgi -b
- PPT在HTML网页上播放方法
项目中遇到一个需求:要求PPT在HTML网页上播放,而且要像电脑一样播放PPT,大家能想到的是什么方法? 印象中我好像有在网上见到过PPT模板网站上的PPT可以播放,赶紧百度搜了下发现都是用第三方软件 ...
- Android为TV端助力 外挂字幕(设置颜色,大小,位置,微调字幕)
前提摘要: 可以给电影加字幕,目前支持srt和ass格式, 功能摘要: 支持微调字幕,设置大小,颜色,位置 1 .字幕解析类 package com.hhzt.iptv.lvb_x.utils; ...
- 新浪短连接API免登陆免认证实例
string source = "source=2849184197"; // APP Key,这个可以根据自己需要去网上搜索 string url_long = $"u ...
- <自动化测试方案_8>第八章、手机端UI自动化测试
第八章.手机端UI自动化测试 (一)APP测试分类 1,原生APP:Native页面是使用原生系统内核的,相当于直接在系统上操作 2,H5APP:先调用系统的浏览器内核,相当于是在网页中进行操作,较原 ...
- 扫码下单与ERP客户端锁桌功能FAQ
一.需求场景:因为目前客户端和平台端有两套数据库,两套数据库通过网络交互信息,且双方都可以发起支付,这种结构容易造成: 1.一笔订单同时支付.一笔订单支付时未按最新订单进行支付,支付多付.支付少付的情 ...
- C# 匿名对象(匿名类型)、var、动态类型 dynamic——实用之:过滤类属性、字段实用dynamic
例子 返回一个LIst<oject>类型 而oject含有 30个字段 而我只需要两个字段.这里实用dynamic 和 linq. 上代码: 注意select new {} 为匿名类型,这 ...
- 这20个常规Python语法你都搞明白了吗?
Python简单易学,但又博大精深.许多人号称精通Python,却不会写Pythonic的代码,对很多常用包的使用也并不熟悉.学海无涯,我们先来了解一些Python中最基本的内容. Python的特点 ...