看懂题目就知道$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]时空旅行的更多相关文章

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

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

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

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

  3. uoj198【CTSC2016】时空旅行

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

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

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

  5. 【CTSC2016】时空旅行

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

  6. Luogu P5416 [CTSC2016]时空旅行

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

  7. [CTSC2016]时空旅行

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

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

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

  9. CTSC2016时空旅行

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

随机推荐

  1. taotao用户登录springMVC拦截器的实现

    在springMVC中写拦截器,只需要两步: 一.写 java 拦截器类,实现 interceptor 拦截器接口. 二.在 springMVC 的xml配置文件中,配置我们创建的拦截器对象及其拦截目 ...

  2. How do I see what character set a database / table / column is in MySQL?

    Q: How do I see what the character set that a MySQL database, table and column are in? Is there some ...

  3. Codeforces Round #524 (Div. 2) A. Petya and Origami

    A. Petya and Origami 题目链接:https://codeforc.es/contest/1080/problem/A 题意: 给出n,k,k表示每个礼品里面sheet的数量(礼品种 ...

  4. Codeforces Round #524 (Div. 2) C. Masha and two friends

    C. Masha and two friends 题目链接:https://codeforc.es/contest/1080/problem/C 题意: 给出一个黑白相间的n*m的矩阵,现在先对一个子 ...

  5. 把java的class文件打成jar包的步骤

    现在我的文件夹的目录在: C:\Users\linsenq\Desktop\cglibjar 我要把位于这个目录下的所有文件夹以及这个文件夹下的.class文件打成jar包 第一步:用win+R 打开 ...

  6. vm虚拟机 开启时报错 无法打开内核设备“\\.\Global\vmx86”: 系统找不到指定的文件。

    解决办法 方案一 1/http://jingyan.baidu.com/article/455a9950aaf4aea167277878.html 方案二 2.http://jingyan.baidu ...

  7. ubuntu安装GraphicsMagick

    一. sudo apt-get install graphicsmagick 二. http://www.cnblogs.com/cocowool/archive/2010/08/16/1800954 ...

  8. 单选按钮radio与文字如何对齐?

    布局如下: <input type="radio" value="立即发送" name="a_1">立即发送 <input ...

  9. codechef T2 Chef and Sign Sequences

    CHEFSIGN: 大厨与符号序列题目描述 大厨昨天捡到了一个奇怪的字符串 s,这是一个仅包含‘<’.‘=’和‘>’三种比较符号的字符串. 记字符串长度为 N,大厨想要在字符串的开头.结尾 ...

  10. swift xcode设置 ,代码折叠,全局折叠 快捷键

    在preference text editing 里面打开 function 折叠的项, 折叠方法快捷键: option+command +left/right 全局折叠快捷键: shift+opti ...