zoukankan      html  css  js  c++  java
  • 【[SCOI2015]情报传递】

    非常无脑的板子题,就当是练一下板子

    我们可以先将所有的操作离线下来,之后那些搜集过情报的点就有了点权,对于查询操作,就是查询一下这条路径上有几个点点权满足(st<=now-C+1)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define re register
    #define maxn 200005
    int n,cnt,tot,m,num;
    int l[maxn*29],r[maxn*29],d[maxn*29];
    int rt[maxn],a[maxn];
    int cur;
    int X[maxn],Y[maxn],C[maxn],Day[maxn];
    int build(int x,int y)
    {
    	int root=++cnt;
    	if(x==y) return root;
    	int mid=x+y>>1;
    	l[root]=build(x,mid),r[root]=build(mid+1,y);
    	return root;
    }
    int change(int pre,int x,int y,int pos)
    {
    	int root=++cnt;
    	d[root]=d[pre]+1;
    	if(x==y) return root;
    	l[root]=l[pre],r[root]=r[pre];
    	int mid=x+y>>1;
    	if(pos<=mid) l[root]=change(l[pre],x,mid,pos);
    		else r[root]=change(r[pre],mid+1,y,pos);
    	return root;
    }
    struct E
    {
    	int v,nxt;
    }e[maxn<<1];
    int head[maxn],sum[maxn],son[maxn],top[maxn],fa[maxn],deep[maxn];
    inline void add_edge(int x,int y)
    {
    	e[++num].v=y;
    	e[num].nxt=head[x];
    	head[x]=num;
    }
    void dfs1(int x)
    {
    	rt[x]=change(rt[fa[x]],1,n+1,a[x]);
    	sum[x]=1;
    	int maxx=-1;
    	for(re int i=head[x];i;i=e[i].nxt)
    	if(!deep[e[i].v])
    	{
    		deep[e[i].v]=deep[x]+1;
    		fa[e[i].v]=x;
    		dfs1(e[i].v);
    		sum[x]+=sum[e[i].v];
    		if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
    	}
    }
    void dfs2(int x,int topf)
    {
    	top[x]=topf;
    	if(!son[x]) return;
    	dfs2(son[x],topf);
    	for(re int i=head[x];i;i=e[i].nxt)
    	if(deep[e[i].v]>deep[x]&&e[i].v!=son[x]) dfs2(e[i].v,e[i].v);
    }
    inline int LCA(int x,int y)
    {
    	while(top[x]!=top[y])
    	{
    		if(deep[top[x]]<deep[top[y]]) std::swap(x,y);
    		x=fa[top[x]];
    	}
    	if(deep[x]<deep[y]) return x;
    	return y;
    }
    inline int read()
    {
    	char c=getchar();
    	int x=0;
    	while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9')
    		x=(x<<3)+(x<<1)+c-48,c=getchar();
    	return x;
    }
    int query(int p1,int p2,int p3,int p4,int x,int y,int ll,int rr)
    {
    	if(ll<=x&&rr>=y) return d[p1]+d[p2]-d[p3]-d[p4];
    	int mid=x+y>>1;
    	if(rr<=mid) return query(l[p1],l[p2],l[p3],l[p4],x,mid,ll,rr);
    	if(ll>mid) return query(r[p1],r[p2],r[p3],r[p4],mid+1,y,ll,rr);
    	return query(l[p1],l[p2],l[p3],l[p4],x,mid,ll,rr)+query(r[p1],r[p2],r[p3],r[p4],mid+1,y,ll,rr);
    }
    int main()
    {
    	n=read();
    	int RT=0,x;
    	for(re int i=1;i<=n;i++)
    	{
    		x=read();
    		if(!x) RT=i;
    			else add_edge(x,i);
    	}
    	rt[0]=build(1,n+1);
    	m=read();
    	int opt;
    	for(re int i=1;i<=m;i++)
    	{
    		opt=read();
    		if(opt==1) X[++cur]=read(),Y[cur]=read(),C[cur]=read(),Day[cur]=i;
    			else a[read()]=i; 
    	}
    	for(re int i=0;i<=n+1;i++)
    	if(!a[i]) a[i]=n+1;
    	rt[0]=change(rt[0],1,n+1,n+1);
    	deep[RT]=1,dfs1(RT),dfs2(RT,RT);
    	for(re int i=1;i<=cur;i++)
    	{
    		int lca=LCA(X[i],Y[i]);
    		printf("%d ",deep[X[i]]+deep[Y[i]]-2*deep[lca]+1);
    		if(Day[i]-C[i]-1<1) puts("0");
    			else printf("%d
    ",query(rt[X[i]],rt[Y[i]],rt[lca],rt[fa[lca]],1,n+1,1,Day[i]-C[i]-1));
    	}
    	return 0;
    }
    
  • 相关阅读:
    抽象类存在的意义
    抽象类的特征
    抽象类的使用
    抽象类的概述
    引用类型作为方法参数和返回值
    继承的特点
    目前Java水平以及理解自我反思---01
    继承后- 构造器的特点
    指针函数
    C数组灵活多变的访问形式
  • 原文地址:https://www.cnblogs.com/asuldb/p/10207880.html
Copyright © 2011-2022 走看看