玄关wa on2求条
查看原帖
玄关wa on2求条
690243
houluyu楼主2024/8/29 18:22
#include<bits/stdc++.h>
using namespace std;
const int N = 200005;//n个点最多连n-1条边 
 
int T, n, m, q;
int fa[N], anc[N][20], val[N], cnt;//val第几个连边从上往下降低 
int dep[N];
int st[N][20];//maxx[i][j]从i往后1<<j个数的最大值
int lg2[N]; 
vector<vector<int> > g(N); 
 
int rd()
{
	int x = 0, f = 1;char c = getchar();
	while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();}
	while(c >= '0' && c <= '9'){x = x * 10 + (c - '0');c = getchar();}
	return x * f;
}
void wt(int x)
{
	if(x < 0)putchar('-'), x = -x;
	if(x > 9)wt(x / 10);
	putchar(x % 10 + '0');
}
void init()
{
	for(int i = 1; i <= n * 2; i ++)
	{
	    val[i] = dep[i] = 0;
	    g[i].clear();
	    fa[i] = i;
	    memset(anc[i], 0, sizeof anc[i]);
	    if(i <= n)memset(st[i], 0, sizeof st[i]);
	}
}
int fd(int x)
{
	if(fa[x] == x)return x;
	return fa[x] = fd(fa[x]);
}
 
void dfs(int u, int fa)
{
	dep[u] = dep[fa] + 1;
	anc[u][0] = fa;
	for(int i = 1; i <= 18; i ++)
		anc[u][i] = anc[anc[u][i - 1]][i - 1];
	for(int i = 0; i < g[u].size(); i ++)
	{
		int v = g[u][i];
		if(v == fa)continue;
		dfs(v, u);
	}
}
 
int lca(int x, int y)
{
	if(dep[x] < dep[y])swap(x, y);
	for(int i = 18; i >= 0; i --)
		if(dep[anc[x][i]] >= dep[y])
			x = anc[x][i];
	if(x == y)return x;
	for(int i = 18; i >= 0; i --)
		if(anc[x][i] != anc[y][i])
			x = anc[x][i], y = anc[y][i];
	return anc[x][0];
}
 
int main()
{
//	cout << log2(N) << endl;//17.6097
	lg2[1] = 0;
	for(int i = 2; i <= N / 2; i ++)
		lg2[i] = lg2[i >> 1] + 1;
	T = rd();
//	scanf("%d", &T);
	while(T --)
	{
		n = rd(), m = rd(), q = rd();
//		scanf("%d%d%d", &n, &m, &q);
		init(); 
		cnt = n; 
		for(int i = 1; i <= m; i ++)
		{
			int u, v;
			u = rd(), v = rd();
//			scanf("%d%d", &u, &v);
			int fa1 = fd(u), fa2 = fd(v);
			if(fa1 == fa2)continue;
			val[++ cnt] = i;//编号为cnt的第i个连上 
			fa[fa1] = cnt;
			fa[fa2] = cnt;
			g[cnt].push_back(fa1);
			g[cnt].push_back(fa2); 
		}
// 		printf("%d\n", cnt);
		dfs(cnt, 0);
		for(int i = 1; i < n; i ++)//i与i+1 联通 
		{
			int u = i, v = i + 1, zx = lca(u, v);//zx是编号 
			st[u][1] = zx;
// 			printf("%d ", st[u][1]);
		} 
// 		printf("\n");
		for(int j = 2; j <= 18; j ++)
			for(int i = 1; i <= n; i ++)
				if(i + (1 << j - 1)<= n)
					st[i][j] = max(st[i][j - 1], st[i + (1 << j - 1)][j - 1]);//编号越大相应边越大
		int l, r, k;
		while(q --)
		{
			l = rd(), r = rd();
//			scanf("%d%d", &l, &r); 
			k = lg2[r - l + 1];
			if(l == r) wt(0);
			else wt(val[max(st[l][k], st[r - (1 << k) + 1][k])]);
			putchar(' ');
		} 
		putchar('\n');
		
	}
	return 0;
 
}
2024/8/29 18:22
加载中...