lca最小公共祖先

D. Dynamic Network

time limit per test

2.0 s

memory limit per test

256 MB

input

standard input

output

standard output

Recently, a startup by a group of students has become more popular and there are plans for expanded offices. Bryan got an internship in this company and his task is to manage its internal network.

The company will acquire some computers over time. Initially, there is only a computer with id=1

. When a new computer is added to the network, it's directly connected to a computer with id=p. The id of the new computer is the minimum positive integer that has not been used as the id

of any other computer.

To determine the performance of the internal network, Bryan is required to answer several queries about what is the minimum number of computers through which a message must go if it is sent from computer with id=u

to computer with id=v (start and end are also counted). Also, when a new computer is added, Bryan has to determine this number for a message sent from the new computer to the computer with id=1

, since it is the most important computer. The computers have enough information to determine the optimum way to send a message to another computer.

Since there could be many computers in the network, Bryan needs your help to write a program that answers the queries. Note that the queries are encoded.

Input

The first line contains an integer Q

(1≤Q≤2∗105) −

the number of queries.

Each of the next Q

line describes a query. It contains a integer t (t∈[1,2]) −

the type of query.

The queries will be encoded. Let last

be the answer for the last query answered and let curr be the number of computers connected in the network so far. Initially last=0 and curr=1

.

  • If t=1
, then one integer p′ follows (0≤p′≤2∗105). Set p=(p′+last)%curr+1. It means that a new computer is connected to the computer with id=p. Increase the value of curr
  • by one.
  • If t=2
  • , then two integers u′ and v′ follow (0≤u′,v′≤2∗105). Set u=(u′+last)%curr+1 and v=(v′+last)%curr+1. It means that a message is sent from computer u to computer v
    • .

    Output

    If the query is of type 1

    , print the number of computers through which a message must go if it is sent from the new computer to computer with id=1

    .

    Otherwise print the amount of computers through which the message must go if it is sent from computer u

    to computer v

    .

    Examples

    Input

    Copy

    7
    1 0
    1 2
    1 2
    1 2
    2 0 4
    2 1 2
    2 2 1
    
    Output

    Copy

    2
    2
    3
    3
    4
    2
    3
    
    Input

    Copy

    6
    1 1
    2 1 2
    1 0
    1 1
    2 0 3
    2 2 2
    
    Output

    Copy

    2
    2
    2
    2
    3
    1
    

    Note

    In the first sample, the new computers are connected as follows

    • Add new computer with id=2
    and connect it to computer with id=1
  • .
  • Add new computer with id=3
  • and connect it to computer with id=1
  • .
  • Add new computer with id=4
  • and connect it to computer with id=2
  • .
  • Add new computer with id=5
  • and connect it to computer with id=2
    • .

    And actual queries of the second type are:

    • u=4
    and v=3
  •  
  • u=1
  • and v=2
  •  
  • u=5
  • and v=4

普通LCA中 fa[i][20]和step[i]需要预处理

https://paste.ubuntu.com/24445999/

int par[max_log_v][max_v];
int depth[max_v];

void dfs(int v, int p, int d)
{
    par[0][v] = p;
    depth[v] = d;
    for(int i = 0;i <(int) G[v].size();i++) {
        if(G[v][i] != p)
            dfs(G[v][i], v, d+1);
    }
}

void init()
{
    dfs(root, -1, 0);

    for(int k = 0;k+1 < max_log_v;k++) {
        for(int v = 0;v < max_v;v++) {
            if(par[k][v] < 0) par[k+1][v] = -1;
            else
                par[k+1][v] = par[k][par[k][v] ];
        }
    }
}
  • #include<bits/stdc++.h>
    using namespace std;
    int Q,t,p,u,v,last,curr=1;
    struct node
    {
    	int step;
    	int f[20];//向上走2^i步到达的节点 
    }a[200005];
    int lca(int u,int v)
    {
    	if(a[u].step<a[v].step) swap(u,v);
    	
    	for(int i=17;i>=0;i--)
    	 	if(a[a[u].f[i]].step>=a[v].step) //二分跳步 
    		 	u=a[u].f[i];//让u和v到同一深度 
    	
    	if(u==v)	return a[u].step;
    		
    	for(int i=17;i>=0;i--) 	////让u和v向上走到同一节点 
    		if(a[u].f[i]!=a[v].f[i]) u=a[u].f[i],v=a[v].f[i];
    		
    	return a[a[u].f[0]].step;
    }
    int main() 
    {
    	scanf("%d",&Q);
    	while(Q--)
    	{
    	a[1].step=1;
    		scanf("%d",&t);
    		if(t==1)
    		{
    			scanf("%d",&p);
    			p=(p+last)%curr+1;
    			curr++;
    			
    			a[curr].step=a[p].step+1;
    			a[curr].f[0]=p;
    			
    			for(int i=1;i<18;i++)
    			{
    				a[curr].f[i]=a[a[curr].f[i-1]].f[i-1];
    				//向上走2^i步到达的节点 
    			}
    						
    			last=a[curr].step; 
    			printf("%d\n",last);
    						
    		}
    		else 
    		{
    			scanf("%d%d",&u,&v);
    			u=(u+last)%curr+1;
    			v=(v+last)%curr+1;
    			int ans=lca(u,v);
    			last=a[u].step+a[v].step-2*ans+1;
    			printf("%d\n",last);	
    		}
    	}
    }
发布了44 篇原创文章 · 获赞 6 · 访问量 1191

猜你喜欢

转载自blog.csdn.net/qq_43868883/article/details/102180321