【NOIP2018模拟赛】到不了

题解:

先把所有操作保存下来,然后离线做,用并查集维护点的连通性。先把初始状态时各点所属的树保存下来备份,然后处理所有连边,处理深度和倍增数组。

之后用保存下来的备份复原,按照顺序操作,操作1就变为了并查集中的合并,操作2就需要判断x和y与另一个其他的相对位置来判断答案,深度最深的即为答案。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<climits>
#include<vector>
#define MAXA 1000005
#define MOD 1000000007
using namespace std;
typedef long long LL;
int head[MAXA],cnt;
struct Rx {
	int next,to;
}edge[MAXA];
struct Rx2 {
	int type,x,y;
}Op[MAXA];
void Add(int u,int v) {
	edge[++cnt].next = head[u];
	edge[cnt].to = v;
	head[u] = cnt;
}
int Ast[MAXA],Depth[MAXA],f[MAXA][21],TreeRoot[MAXA],Ans,Temp;
int FindAst(int x) {
	if(Ast[x] == x)
	   return x;
	Ast[x] = FindAst(Ast[x]);
	return Ast[x];
}
void DFS(int x,int Root) {
	TreeRoot[x] = Root;
	for(int i=head[x];i;i=edge[i].next) {
		int y = edge[i].to;
		if(y == f[x][0]) continue;
		f[y][0] = x;
		DFS(y,Root);
	}
}
void DFS2(int x) {
	Depth[x] = Depth[f[x][0]] + 1;
	for(int i=head[x];i;i=edge[i].next) {
		int y = edge[i].to;
		if(y == f[x][0]) continue;
		f[y][0] = x;
		DFS2(y);
	}
}
int LCA(int x,int y) {
	if(Depth[x] < Depth[y])
	   swap(x,y);
	for(int i=18;i>=0;i--)
	    if(Depth[f[x][i]] >= Depth[y])
	       x = f[x][i];
	if(x == y) return x;
	for(int i=18;i>=0;i--)
	    if(f[x][i] != f[y][i]) {
	    	x = f[x][i];
	    	y = f[y][i];
		}
	return f[x][0];
}
int n,m,x,y,Q,E;
int Root[MAXA];
int main() {
//	freopen("data.in","r",stdin);
//	freopen("data.out","w",stdout);
	scanf("%d %d",&n,&m);
	for(int i=1;i<=m;i++)
		scanf("%d",&Root[i]);
	scanf("%d",&E);
	for(int i=1;i<=n-m;i++) {
		scanf("%d %d",&x,&y);
		Add(x,y);
		Add(y,x);
	}
	for(int i=1;i<=m;i++)
	    DFS(Root[i],Root[i]);
	memcpy(Ast,TreeRoot,sizeof(Ast));
	scanf("%d",&Q);
	for(int i=1;i<=Q;i++) {
		scanf("%d %d %d",&Op[i].type,&Op[i].x,&Op[i].y);
		if(Op[i].type == 1) {
			if(FindAst(Op[i].x) == FindAst(Op[i].y)) continue;
			Ast[FindAst(Op[i].y)] = FindAst(Op[i].x);
			Add(Op[i].x,Op[i].y);
			Add(Op[i].y,Op[i].x);
		}
	}
	for(int i=1;i<=n;i++)
	    f[i][0] = 0;
	for(int i=1;i<=m;i++)
	    if(FindAst(Root[i]) == Root[i])
	       DFS2(Root[i]);
	
	for(int j=1;j<=18;j++)
	    for(int i=1;i<=n;i++)
	        f[i][j] = f[f[i][j-1]][j-1];
	memcpy(Ast,TreeRoot,sizeof(Ast));
	for(int i=1;i<=Q;i++) {
		if(Op[i].type == 1) {
			if(FindAst(Op[i].x) == FindAst(Op[i].y)) continue;
			Ast[FindAst(Op[i].y)] = FindAst(Op[i].x);
		}
		else {
			if(FindAst(Op[i].x) != FindAst(Op[i].y)) {
				printf("orzorz\n");
				continue;
			}
			int xAst = FindAst(Op[i].x);
			Ans = LCA(Op[i].x,Op[i].y);
			Temp = LCA(Op[i].x,xAst);
			if(Depth[Temp] > Depth[Ans]) Ans = Temp;
			Temp = LCA(Op[i].y,xAst);
			if(Depth[Temp] > Depth[Ans]) Ans = Temp;
			printf("%d\n",Ans);
		}
	}
	
}
/*
9 3
1 5 8
1 2
1 3
2 4
5 6
5 7
8 9
4
1 6 1
1 6 8
2 9 2
2 4 7
*/

猜你喜欢

转载自blog.csdn.net/qq_41513352/article/details/82933767
今日推荐