zoukankan      html  css  js  c++  java
  • luogu P5416 [CTSC2016]时空旅行

    luogu

    uoj

    注意到用这个集合产生方式可以构建出一个树型结构,并且每个加入/删除元素都是对应的一个子树的范围,对应到dfs序上就是每次对一个区间内的集合加入/删除元素,所以可以线段树分治,把每种元素的出现区间整出来

    把答案柿子((x-x_0)^2+c)拆开,得到(x^2-2x*x_0+{x_0}^2+c),然后每个元素就相当于斜率为(-2x),截距为(x^2+c)的直线,所以线段树每个节点维护凸壳,要用的时候直接查对应横坐标的值.如果直接做是两个(log)的,但是因为要答案最小,所以可以按照斜率从大到小((x)从小到大)的顺序插入元素对应的直线,然后按照(x_0)从小到大查询,这样由于插入和查询的单调性所以可以少掉一个log

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define LL long long
    #define uLL unsigned long long
    #define db double
    
    using namespace std;
    const int N=5e5+10;
    LL rd()
    {
    	LL x=0,w=1;char ch=0;
    	while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    	return x*w;
    }
    struct node
    {
    	LL x,y;
    }a[N],qr[N];
    vector<int> ti[N],e[N];
    LL an[N];
    int n,m,q,fa[N],ty[N],sz[N],dfn[N],tt,sb[N];
    bool cmp1(int aa,int bb){return a[aa].x!=a[bb].x?a[aa].x<a[bb].x:a[aa].x*a[aa].x+a[aa].y>a[bb].x*a[bb].x+a[bb].y;}
    bool cmp2(int aa,int bb){return qr[aa].x<qr[bb].x;}
    void dfs(int x)
    {
    	dfn[x]=++tt,sz[x]=1;
    	ti[ty[x]].push_back(dfn[x]);
    	vector<int>::iterator it;
    	for(it=e[x].begin();it!=e[x].end();++it)
    	{
    		int y=*it;
    		dfs(y),sz[x]+=sz[y];
    	}
    	ti[ty[x]].push_back(dfn[x]+sz[x]);
    }
    struct line
    {
    	db k,b;
    	line(){}
    	line(LL x,LL y){k=-2*x,b=x*x+y;}
    };
    db jiao(line aa,line bb){return (bb.b-aa.b)/(aa.k-bb.k);}
    struct HULL
    {
    	vector<line> qu;
    	int hd,tl;
    	HULL(){hd=0,tl=-1;}
    	void inst(line aa)
    	{
    		if(hd<=tl&&qu[tl].k==aa.k) qu.pop_back(),--tl;
    		while(hd<tl&&jiao(aa,qu[tl])<=jiao(qu[tl],qu[tl-1])) qu.pop_back(),--tl;
    		qu.push_back(aa),++tl;
    	}
    	LL quer(LL x)
    	{
    		while(hd<tl&&x>=jiao(qu[hd],qu[hd+1])) ++hd;
    		return hd<=tl?(LL)round(qu[hd].k*(db)x+qu[hd].b):1ll<<50;
    	}
    }hl[N<<2];
    #define mid ((l+r)>>1)
    int ps[N];
    void setli(int o,int l,int r,int ll,int rr,line x)
    {
    	if(ll<=l&&r<=rr){hl[o].inst(x);return;}
    	if(ll<=mid) setli(o<<1,l,mid,ll,rr,x);
    	if(rr>mid) setli(o<<1|1,mid+1,r,ll,rr,x);
    }
    void bui(int o,int l,int r)
    {
    	if(l==r){ps[l]=o;return;}
    	bui(o<<1,l,mid),bui(o<<1|1,mid+1,r);
    }
    
    int main()
    {
    	n=rd(),q=rd();
    	a[++m]=(node){0,rd()};
    	ty[1]=1;
    	for(int i=2;i<=n;++i)
    	{
    		int op=rd();
    		fa[i]=rd()+1;
    		int ii=rd()+1;
    		e[fa[i]].push_back(i);
    		ty[i]=ii;
    		m=max(m,ii);
    		if(op==0)
    		{
    			a[ii].x=rd();
    			rd(),rd();
    			a[ii].y=rd();
    		}
    	}
    	dfs(1);
    	for(int i=1;i<=n;++i) sb[i]=i;
    	sort(sb+1,sb+n+1,cmp1);
    	for(int i=1;i<=n;++i)
    	{
    		int ii=sb[i],nn=ti[ii].size();
    		for(int j=0;j+1<nn;j+=2)
    			if(ti[ii][j]<=ti[ii][j+1]-1)
    				setli(1,1,n,ti[ii][j],ti[ii][j+1]-1,line(a[ii].x,a[ii].y));
    	}
    	for(int i=1;i<=q;++i)
    	{
    		int y=rd()+1,x=rd();
    		qr[i]=(node){x,y};
    	}
    	for(int i=1;i<=q;++i) sb[i]=i;
    	sort(sb+1,sb+q+1,cmp2);
    	bui(1,1,n);
    	for(int i=1;i<=q;++i)
    	{
    		int ii=sb[i],es=qr[ii].y;
    		LL y=qr[ii].x;
    		int o=ps[dfn[es]];
    		an[ii]=1ll<<50;
    		while(o)
    		{
    			an[ii]=min(an[ii],y*y+hl[o].quer(y));
    			o>>=1;
    		}
    	}
    	for(int i=1;i<=q;++i) printf("%lld
    ",an[i]);
    	return 0; 
    }
    
  • 相关阅读:
    Azure HPC Pack Cluster添加辅助节点
    Azure HPC Pack 辅助节点模板配置
    Azure HPC Pack配置管理系列(PART6)
    Windows HPC Pack 2012 R2配置
    Azure HPC Pack 节点提升成域控制器
    Azure HPC Pack VM 节点创建和配置
    Azure HPC Pack 部署必要条件准备
    Azure HPC Pack 基础拓扑概述
    Azure VM 性能计数器配置
    Maven私仓配置
  • 原文地址:https://www.cnblogs.com/smyjr/p/11507520.html
Copyright © 2011-2022 走看看