HDU 3078 LCA转RMQ

题意:

n个点 m个询问

下面n个数字表示点权值

n-1行给定一棵树

m个询问 k u v

k为0时把u点权值改为v

或者问 u-v的路径上 第k大的数

思路:

LCA转RMQ求出 LCA(u,v) ;

登山坡式找到路径上所有点并记录其权值

排序输出k大的数

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<queue>
#include<string.h>
#include<map>
#include<set>
#include<stack>
#include<vector>
#include<math.h>
#define N 80010
using namespace std;
inline int Max(int a,int b){return a>b?a:b;}

struct node{
	int from, to, nex;
}edge[N<<1];
int head[N], edgenum;
void addedge(int u, int v){
	node E = {u, v, head[u]};
	edge[ edgenum ] = E;
	head[u] = edgenum ++;
}
int val[N], Stack[N];

int time;
int deep[N<<1], index[N<<1], first[N], pre[N];
void DFS(int u, int dep){
	deep[time] = u;
	index[time] =u;
	time++;
	for(int i = head[u]; i !=-1; i = edge[i].nex)
	{
		int v = edge[i].to;
		if(first[v] == 0)
		{
			first[v] = time;
			pre[v] = u;
			DFS(v, dep+1);
			deep[time] = u;
			index[time]= u;
			time++;
		}
	}
}
int dp[N<<1][25];
void RMQ_init(int n){
	for(int i = 1; i <= n; i++)
		dp[i][0] = i;
	for(int j = 1; (1<<j)<=n;j++)
	{
		int k = 1<<(j-1);
		for(int i = 1; i+k<n; i++)
		{
			if(deep[ dp[i][j-1] ] <= deep[ dp[i+k][j-1] ])
				dp[i][j] = dp[i][j-1];
			else 
				dp[i][j] = dp[i+k][j-1];
		}
	}
}
int RMQ(int a,int b){
	int dis = Max(a-b,b-a) +1;
	int k = log(double(dis))/ log(2.0);
	if(deep[dp[a][k]]<= deep[dp[b - (1<<k) +1][k]])
		return dp[a][k];
	else
	return dp[b-(1<<k)+1][k];
}
int LCA(int u, int v){
	int fu = first[u], fv = first[v];
	return fu<=fv? index[ RMQ(fu,fv)] : index[ RMQ(fv,fu)];
}

int main()
{
	int n, m, i, j, k, que, u, v;
	int root = 1;
	while(~scanf("%d%d",&n,&que))
	{
		memset(head, -1, sizeof(head)); edgenum = 0;
		memset(first, 0, sizeof(first));

		for(i=1;i<=n;i++)scanf("%d",&val[i]);
		for(i=1;i<n;i++)
		{
			scanf("%d %d",&u,&v);
			addedge(u, v);	addedge(v, u);
		}
		first[root] = 1;
		time = 1;
		DFS(root, 0);
		RMQ_init(time-1);
		while(que--){
			scanf("%d %d %d",&k,&u,&v);
			if(k==0)
			{val[u] = v; continue;}
			if(u==v){
				if(k==1)printf("%d
",val[u]);
				else printf("invalid request!
");continue;
			}
			int c = LCA(u, v);
			int top = 0;
			Stack[top++] = val[c];
			while(u!=c)
			{
				Stack[top++] = val[u];
				u = pre[u];
			}
			while(v!=c)
			{
				Stack[top++] = val[v];
				v = pre[v];
			}
			if(top<k)
			{printf("invalid request!
");continue;}
			sort(Stack, Stack+top);
			printf("%d
",Stack[top - k]);
		}
	}
	return 0;
}


 

8 99
5 2 3 4 5 6 7 8
1 3
1 2
3 4 
3 5 
5 6
5 7
7 8
1 2 8
2 2 8
3 2 8
4 2 8
5 2 8
6 2 8
7 2 8
1 4 8
4 2 3
5 3 8
2 3 8
0 3 8
2 3 8
3 3 8
2 4 5
1 4 1
2 4 1
3 4 1

ans:
8
7
5
5
3
2
in...
8
in...
in...
7
8
7
5
8
5
4

1 1
5
1 1 1

ans:
5



2 2
2 1
1 2
2 2 1
1 1 2

ans:
1
2


 

原文地址:https://www.cnblogs.com/riskyer/p/3424061.html