Mnzn 求助树上倍增
查看原帖
Mnzn 求助树上倍增
430409
Coros_Trusds楼主2022/1/5 22:48
//2022/1/4

//2022/1/5

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>

#include <cstdio>

#include <climits>//need "INT_MAX","INT_MIN"

#include <cstring>//need "memset"

#include <algorithm>
 
#define enter() putchar(10)

#define debug(c,que) cerr<<#c<<" = "<<c<<que

#define cek(c) puts(c)

#define blow(arr,st,ed,w) for(register int i=(st);i<=(ed);i++)cout<<arr[i]<<w;

#define speed_up() cin.tie(0),cout.tie(0)

#define endl "\n"

#define Input_Int(n,a) for(register int i=1;i<=n;i++)scanf("%d",a+i);

#define Input_Long(n,a) for(register long long i=1;i<=n;i++)scanf("%lld",a+i);

#define mst(a,k) memset(a,k,sizeof(a))

namespace Newstd
{
	inline int read()
	{
		int x=0,k=1;
		char ch=getchar();
		while(ch<'0' || ch>'9')
		{
			if(ch=='-')
			{
				k=-1;
			}
			ch=getchar();
		}
		while(ch>='0' && ch<='9')
		{
			x=(x<<1)+(x<<3)+ch-'0';
			ch=getchar();
		}
		return x*k;
	}
	inline void write(int x)
	{
		if(x<0)
		{
			putchar('-');
			x=-x;
		}
		if(x>9)
		{
			write(x/10);
		}
		putchar(x%10+'0');
	}
}

using namespace Newstd;

using namespace std;

const int INF=0x3f3f3f3f;

const int ma=1e5+5;

struct Gragh
{
	int v;
	
	int nxt;
};

Gragh gra[ma<<1];

int head[ma],dep[ma],lg[ma],res1[ma],res2[ma];

int fa[ma][31],w[ma][21];

int dis[ma][31][21];
//dis[i][j][k]:i 向上跳 2^{j}-1 步后第 k 小的值 

int n,m,q;

int idx;

inline void add(int u,int v)
{
	gra[++idx].v=v;
	
	gra[idx].nxt=head[u];
	
	head[u]=idx;
}

inline void init()
{
	for(register int i=1;i<=n;i++)
	{
		lg[i]=lg[i>>1]+1;
	}
}

inline void dfs(int now,int fath,int depth)
{
	fa[now][0]=fath;
	
	dep[now]=depth;
	
	for(register int i=head[now];i;i=gra[i].nxt)
	{
		int v=gra[i].v;
		
		if(v!=fath)
		{
			dfs(v,now,depth+1);
		}
	}
}

inline int LCA(int x,int y)
{
	if(dep[x]<dep[y])
	{
		swap(x,y);
	}
	
	while(dep[x]>dep[y])
	{
		x=fa[x][lg[dep[x]-dep[y]]-1];
	}
	
	if(x==y)
	{
		return x;
	}
	
	for(register int i=30;i>=0;i--)
	{
		if(fa[x][i]!=fa[y][i])
		{
			x=fa[x][i];
			
			y=fa[y][i];
		}
	}
	
	return fa[x][0];
}

inline void updata1(int x,int y)
{
	mst(res1,0x3f);
	
	for(register int i=30;i>=0;i--)
	{
		if(dep[x]>=dep[y]+(1<<i))
		{
			for(register int j=1;j<=10;j++)
			{
				res1[j+10]=dis[x][i][j];
			}
			
			sort(res1+1,res1+20+1);
			
			x=fa[x][i];
		}
	}
}

inline void updata2(int x,int y)
{
	mst(res2,0x3f);
	
	for(register int i=30;i>=0;i--)
	{
		if(dep[x]>=dep[y]+(1<<i))
		{
			for(register int j=1;j<=10;j++)
			{
				res2[j+10]=dis[x][i][j];
			}
			
			sort(res2+1,res2+20+1);
			
			x=fa[x][i];
		}
	}
}

inline void query(int x,int y,int a)
{
	int ans=0;
	
	int lca=LCA(x,y);
	
	if(lca==x)
	{
		updata1(y,x);
		
		for(register int i=1;i<=10;i++)
		{
			res1[i+10]=w[x][i];
		}
		
		sort(res1+1,res1+20+1);
		
		for(register int i=1;i<=a;i++)
		{
			if(res1[i]!=INF)
			{
				ans++;
			}
		}
		
		printf("%d ",ans);
		
		for(register int i=1;i<=a;i++)
		{
			if(res1[i]!=INF)
			{
				printf("%d ",res1[i]);
			}
		}
		
		enter();
	}
	
	else if(lca==y)
	{
		swap(x,y);
		
		updata1(y,x);
		
		for(register int i=1;i<=10;i++)
		{
			res1[i+10]=w[x][i];
		}
		
		sort(res1+1,res1+20+1);
		
		for(register int i=1;i<=a;i++)
		{
			if(res1[i]!=INF)
			{
				ans++;
			}
		}
		
		printf("%d ",ans);
		
		for(register int i=1;i<=a;i++)
		{
			if(res1[i]!=INF)
			{
				printf("%d ",res1[i]);
			}
		}
		
		enter();
	}
	
	else
	{
		updata1(x,lca);
		
		updata2(y,lca);
		
		for(register int i=1;i<=10;i++)
		{
			res1[i+10]=res2[i];
		}
		
		sort(res1+1,res1+20+1);
		
		for(register int i=1;i<=10;i++)
		{
			res1[i+10]=w[lca][i];
		}
		
		sort(res1+1,res1+20+1);
		
		for(register int i=1;i<=a;i++)
		{
			if(res1[i]!=INF)
			{
				ans++;
			}
		}
		
		printf("%d ",ans);
		
		for(register int i=1;i<=a;i++)
		{
			if(res1[i]!=INF)
			{
				printf("%d ",res1[i]);
			}
		}
		
		enter();
	}
}

int main(void)
{
	mst(w,0x3f);mst(dis,0x3f);
	
	n=read(),m=read(),q=read();
	
	for(register int i=1;i<n;i++)
	{
		int u=read(),v=read();
		
		add(u,v),add(v,u);
	}
	
	for(register int i=1;i<=m;i++)
	{
		int x=read();
		
		w[x][11]=i;
		
		sort(w[x]+1,w[x]+11+1);
	}
	
	init();
	
	dfs(1,0,1);
	
	for(register int i=1;i<=n;i++)
	{
		for(register int j=1;j<=10;j++)
		{
			dis[i][0][j]=w[i][j];
		}
	}
	
	for(register int j=1;j<=30;j++)
	{
		for(register int i=1;i<=n;i++)
		{
			fa[i][j]=fa[fa[i][j-1]][j-1];
			
			for(register int k=1;k<=10;k++)
			{
				dis[i][j][k]=dis[fa[i][j-1]][j-1][k];
				
				dis[i][j][k+10]=dis[i][j-1][k];
			}
			
			sort(dis[i][j]+1,dis[i][j]+20+1);
		}
	}
	
	while(q--)
	{
		int u=read(),v=read(),a=read();
		
		query(u,v,a);
	}
	
	return 0;
}

对着改的代码(快改得一模一样了):

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
namespace Quick_Function {
	template <typename Temp> void Read(Temp &x) {
		x = 0;
		char ch = getchar();
		bool op = 0;
		while (ch < '0' || ch > '9') {
			if (ch == '-') op = 1;
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9') {
			x = (x << 1) + (x << 3) + (ch ^ 48);
			ch = getchar();
		}
		if (op) x = -x;
	}
	template <typename T, typename... Args> void Read(T &t, Args &... args) {
		Read(t);
		Read(args...);
	}
	template <typename Temp> Temp Max(Temp x, Temp y) {
		return x > y ? x : y;
	}
	template <typename Temp> Temp Min(Temp x, Temp y) {
		return x < y ? x : y;
	}
	template <typename Temp> Temp Abs(Temp x) {
		return x < 0 ? (-x) : x;
	}
	template <typename Temp> void Swap(Temp &x, Temp &y) {
		x ^= y ^= x ^= y;
	}
}
using namespace Quick_Function;
#define INF 0x3f3f3f3f
const int MAXN = 1e5 + 5;
struct Edge {
	int Next, To;
};
Edge edge[MAXN << 1];
int head[MAXN], edgetot = 1;
void Addedge(int u, int v) {
	edge[++edgetot].Next = head[u], edge[edgetot].To = v, head[u] = edgetot;
	edge[++edgetot].Next = head[v], edge[edgetot].To = u, head[v] = edgetot;
}
int w[MAXN][21];
int n, m, q, a;
int dep[MAXN], fa[MAXN][31], dis[MAXN][31][21];
int res1[21], res2[21];
int Get_Lca(int x, int y) {
	if (dep[x] < dep[y]) Swap(x, y);
	for (int i = 30; i >= 0; i--)
		if (dep[x] - (1 << i) >= dep[y]) x = fa[x][i];
	if (x == y) return x;
	for (int i = 30; i >= 0; i--)
		if (fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
	return fa[x][0];
}
void dfs(int u, int step) {
	dep[u] = step;
	for (int i = head[u]; i; i = edge[i].Next) {
		int v = edge[i].To;
		if (v != fa[u][0]) {
			fa[v][0] = u;
			dfs(v, step + 1);
		}
	}
}
void Upclimb1(int x, int y) {
	memset(res1, 0x3f, sizeof(res1));
	for (int i = 30; i >= 0; i--)
		if (dep[x] - (1 << i) >= dep[y]) {
			for (int k = 1; k <= 10; k++) res1[k + 10] = dis[x][i][k];
			sort(res1 + 1, res1 + 1 + 20);
			x = fa[x][i];
		}
}
void Upclimb2(int x, int y) {
	memset(res2, 0x3f, sizeof(res2));
	for (int i = 30; i >= 0; i--)
		if (dep[x] - (1 << i) >= dep[y]) {
			for (int k = 1; k <= 10; k++) res2[k + 10] = dis[x][i][k];
			sort(res2 + 1, res2 + 1 + 20);
			x = fa[x][i];
		}
}
void Query(int x, int y) {
	int ans = 0;
	int lca = Get_Lca(x, y);
	if (lca == x) {
		Upclimb1(y, x);
		for (int i = 1; i <= 10; i++) res1[i + 10] = w[x][i];
		sort(res1 + 1, res1 + 1 + 20);
		for (int i = 1; i <= a; i++)
			if (res1[i] != INF) ans++;
		printf("%d ", ans);
		for (int i = 1; i <= a; i++)
			if (res1[i] != INF) printf("%d ", res1[i]);
		return;
	}
	if (lca == y) {
		Swap(x, y);
		Upclimb1(y, x);
		for (int i = 1; i <= 10; i++) res1[i + 10] = w[x][i];
		sort(res1 + 1, res1 + 1 + 20);
		for (int i = 1; i <= a; i++)
			if (res1[i] != INF) ans++;
		printf("%d ", ans);
		for (int i = 1; i <= a; i++)
			if (res1[i] != INF) printf("%d ", res1[i]);
		return;
	}
	Upclimb1(x, lca);
	Upclimb2(y, lca);
	for (int i = 1; i <= 10; i++) res1[i + 10] = res2[i];
	sort(res1 + 1, res1 + 1 + 20);
	for (int i = 1; i <= 10; i++) res1[i + 10] = w[lca][i];
	sort(res1 + 1, res1 + 1 + 20);
	for (int i = 1; i <= a; i++)
		if (res1[i] != INF) ans++;
	printf("%d ", ans);
	for (int i = 1; i <= a; i++)
		if (res1[i] != INF) printf("%d ", res1[i]);
}
int main() {
	memset(w, 0x3f, sizeof(w));
	memset(dis, 0x3f, sizeof(dis));
	Read(n, m, q);
	for (int i = 1, u, v; i < n; i++)
		Read(u, v), Addedge(u, v);
	for (int i = 1, a; i <= m; i++) {
		Read(a);
		w[a][11] = i;
		sort(w[a] + 1, w[a] + 1 + 11);
	}
	dfs(1, 0);
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= 10; j++) dis[i][0][j] = w[i][j];
	for (int j = 1; j <= 30; j++)
		for (int i = 1; i <= n; i++) {
			fa[i][j] = fa[fa[i][j - 1]][j - 1];
			for (int k = 1; k <= 10; k++) 
				dis[i][j][k] = dis[fa[i][j - 1]][j - 1][k];
			for (int k = 1; k <= 10; k++) 
				dis[i][j][k + 10] = dis[i][j - 1][k];
			sort(dis[i][j] + 1, dis[i][j] + 1 + 20);
		}
	int u, v;
	while (q--) {
		Read(u, v, a);
		Query(u, v);
		printf("\n");
	}
	return 0;
}
2022/1/5 22:48
加载中...