• 【CF725G】Messages on a Tree 树链剖分+线段树


    【CF725G】Messages on a Tree

    题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王。现在一些跳蚤要给跳蚤国王发信息。具体的信息传输过程如下:

    1.信息的发起者把信息上传给他父亲节点处的跳蚤,然后自身进入等待状态。
    3.跳蚤国王在收到信息时会将信息立刻下传到发来信息的那个儿子,跳蚤国王可以在同一时刻下传多份信息。
    4.:a把信息传给b。如果b正处于等待状态,则b会立刻将a发来的信息下传回去。如果同时有好多个信息传给b,则b会接受其中发起者编号最小的那个,并将其余的下传回去。如果上传成功,b会接着把信息上传给它的父亲,然后自身进入等待状态。
    5.下传:b把信息传给a。解除a的等待状态,接着a继续把信息向着发起者下传过去。如果同时有信息上传下传到a,视为先下传上传
    6.当发起者收到下传回来的信息后,传输结束。
    7.上传下传所需时间都是1秒。
    8.如果信息的发起者在发出信息时正处于等待状态,该信息直接结束。

    现在给你m个时间,第i个事件形如:编号为a的跳蚤在t时刻发起了一次信息传输。现在问你每个信息传输的结束时间是多少。

    题解:先将所有时间按$dep_a+t$排序,不难发现排序后只有前面的事件会影响后面的事件,然后我们依次处理每个事件。如果a在上传过程中停在了节点v处,而v正在等待来自b的消息,则一定满足:$dep_a-dep_v+t_a<T_b-(dep_b-dep_v)$,其中T表示结束时间。所以我们可以用树链剖分+线段树维护,然后在链上二分即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define lson x<<1
    #define rson x<<1|1
    using namespace std;
    const int maxn=200010;
    const int inf=2000000000;
    int n,m,cnt;
    int to[maxn],nxt[maxn],head[maxn],fa[maxn],p[maxn],q[maxn],dep[maxn],siz[maxn],son[maxn],top[maxn];
    int sd[maxn<<2],s[maxn<<2],tag[maxn<<2],ans[maxn];
    struct node
    {
    	int x,t,org;
    }t[maxn];
    void dfs(int x,int tp)
    {
    	top[x]=tp;
    	p[x]=++q[0],q[q[0]]=x;
    	if(son[x])	dfs(son[x],tp);
    	for(int i=head[x];i!=-1;i=nxt[i])	if(to[i]!=son[x])	dfs(to[i],to[i]);
    }
    inline void add(int a,int b)
    {
    	to[cnt]=b,nxt[cnt]=head[a],head[a]=cnt++;
    }
    void build(int l,int r,int x)
    {
    	s[x]=tag[x]=-inf;
    	if(l==r)
    	{
    		sd[x]=dep[q[l]]<<1;
    		return ;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,lson),build(mid+1,r,rson);
    	sd[x]=max(sd[lson],sd[rson]);
    }
    inline void upd(int x,int y)
    {
    	s[x]=max(s[x],sd[x]+y),tag[x]=max(tag[x],y);
    }
    inline void pushdown(int x)
    {
    	if(tag[x]!=-inf)	upd(lson,tag[x]),upd(rson,tag[x]),tag[x]=-inf;
    }
    void updata(int l,int r,int x,int a,int b,int c)
    {
    	if(a<=l&&r<=b)
    	{
    		upd(x,c);
    		return ;
    	}
    	pushdown(x);
    	int mid=(l+r)>>1;
    	if(a<=mid)	updata(l,mid,lson,a,b,c);
    	if(b>mid)	updata(mid+1,r,rson,a,b,c);
    	s[x]=max(s[lson],s[rson]);
    }
    int query(int l,int r,int x,int a,int b)
    {
    	if(a<=l&&r<=b)	return s[x];
    	pushdown(x);
    	int mid=(l+r)>>1;
    	if(b<=mid)	return query(l,mid,lson,a,b);
    	if(a>mid)	return query(mid+1,r,rson,a,b);
    	return max(query(l,mid,lson,a,b),query(mid+1,r,rson,a,b));
    }
    bool cmp(const node &a,const node &b)
    {
    	return (dep[a.x]+a.t==dep[b.x]+b.t)?(a.x<b.x):(dep[a.x]+a.t<dep[b.x]+b.t);
    }
    int solve(int x,int t)
    {
    	if(x==11)
    	{
    		x++,x--;
    	}
    	int u=x;
    	while(u)
    	{
    		if(query(1,n,1,p[top[u]],p[u])<=dep[x]+t)
    		{
    			u=fa[top[u]];
    			continue;
    		}
    		int l=p[top[u]]+1,r=p[u]+1,mid;
    		while(l<r)
    		{
    			mid=(l+r)>>1;
    			if(query(1,n,1,mid,p[u])>dep[x]+t)	l=mid+1;
    			else	r=mid;
    		}
    		u=q[l-1];
    		break;
    	}
    	if(!u)	u=1;
    	int ret=2*(dep[x]-dep[u])+t,v=x;
    	while(top[v]!=top[u])
    	{
    		updata(1,n,1,p[top[v]],p[v],ret-dep[x]),v=fa[top[v]];
    	}
    	updata(1,n,1,p[u],p[v],ret-dep[x]);
    	return ret;
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	int i;
    	n=rd()+1,m=rd();
    	dep[1]=1;
    	memset(head,-1,sizeof(head));
    	for(i=2;i<=n;i++)	fa[i]=rd()+1,add(fa[i],i),dep[i]=dep[fa[i]]+1;
    	for(i=n;i>=2;i--)
    	{
    		siz[i]++,siz[fa[i]]+=siz[i];
    		if(siz[i]>siz[son[fa[i]]])	son[fa[i]]=i;
    	}
    	dfs(1,1);
    	build(1,n,1);
    	for(i=1;i<=m;i++)	t[i].x=rd()+1,t[i].t=rd(),t[i].org=i;
    	sort(t+1,t+m+1,cmp);
    	for(i=1;i<=m;i++)
    	{
    		ans[t[i].org]=solve(t[i].x,t[i].t);
    	}
    	for(i=1;i<=m;i++)	printf("%d ",ans[i]);
    	return 0;
    }//10 9 0 0 0 3 0 4 5 3 8 6 1 6 1 13 5 14 1 16 5 18 7 18 10 21 6 22 4 22
  • 相关阅读:
    发现pythonWin里面的一个地方挺别扭
    细节-质量-态度
    对于Borland出售IDE业务的一点感想
    ReView100遍?!
    代码生成原则Top10
    使用asp.net进行多关键字查询的例子
    代码生成FAQ(翻译)
    msdn中文上的几篇有用的sqlServer2000的文章
    RSS 阅读工具Omea Reader
    Ubuntu18.04 安装Postgresql12
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/8503836.html
Copyright © 2020-2023  润新知