Codeforces 1706E. Qpwoeirut and Vertices

\(\texttt{Difficulty:2300}\)

题目大意

思路

即求若干点两两之间路径上最大边权的最小值,显然 \(\texttt{Kruskal}\) 重构树即可解决,询问点的区间为 \([l,r]\) , 答案即为 \([l,r]\) 所有点在重构树上的 \(lca\) 的点权,\([l,r]\) 所有点的 \(lca\)\(lca(dfn最小的,dfn最大的)\) ,随遍一种快速查询区间 \(min,max\) 的方法即可,复杂度 \(O(nlogn)\)

代码

#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
using namespace std;
using LL = long long;
using LD = long double;
using ULL = unsigned long long;
using PII = pair<LL, LL>;
using TP = tuple<int, int, int>;
#define all(x) x.begin(),x.end()
#define mst(x,v) memset(x,v,sizeof(x))
#define mk make_pair
//#define int LL
#define double LD
//#define lc p*2
//#define rc p*2+1
#define endl '\n'
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#pragma warning(disable : 4996)
#define IOS ios::sync_with_stdio(0),cin.tie(0),cout.tie(0)
const double eps = 1e-8;
const double pi = acos(-1);
const LL MOD = 1000000007;
const LL mod = 998244353;
const int maxn = 300010;

int T, N, M, Q;

struct Edge {
	int u, v, cost;
};

bool cmp(Edge& e1, Edge& e2)
{
	return e1.cost < e2.cost;
}

int par[maxn], rk[maxn];

void init(int n)
{
	for (int i = 1; i <= n; i++)
	{
		par[i] = i;
		rk[i] = 0;
	}
}

int find(int x)
{
	if (x == par[x])
		return x;
	return par[x] = find(par[x]);
}

void unite(int x, int y)
{
	x = find(x), y = find(y);
	if (x == y)
		return;
	par[y] = x;
}

bool same(int x, int y)
{
	return find(x) == find(y);
}

vector<int>G[maxn];
vector<Edge> es;
int val[maxn], cntv, cnte;

void add_edge(int from, int to)
{
	G[from].push_back(to);
	G[to].push_back(from);
}

void Kruskal()
{
	sort(all(es), cmp), init(cntv);
	for (auto& e : es)
	{
		int u = e.u, v = e.v;
		if (!same(u, v))
		{
			int fu = find(u), fv = find(v);
			cntv++;
			par[cntv] = cntv, rk[cntv] = 0;
			add_edge(fu, cntv), add_edge(cntv, fv);
			unite(cntv, fu), unite(cntv, fv);
			val[cntv] = e.cost;
		}
		if (cntv == N * 2 - 1)
			break;
	}
}

int fa[maxn], dep[maxn], siz[maxn], hson[maxn], top[maxn], dfn[maxn], rnk[maxn], tot;

void dfs1(int v, int p, int d)
{
	fa[v] = p, dep[v] = d, siz[v] = 1;
	for (auto& to : G[v])
	{
		if (to == p)
			continue;
		dfs1(to, v, d + 1);
		siz[v] += siz[to];
		if (!hson[v] || siz[to] > siz[hson[v]])
			hson[v] = to;
	}
}

void dfs2(int v, int p, int t)
{
	dfn[v] = ++tot, rnk[tot] = v, top[v] = t;
	if (!hson[v])
		return;
	dfs2(hson[v], v, t);
	for (auto& to : G[v])
	{
		if (to == p || to == hson[v])
			continue;
		dfs2(to, v, to);
	}
}

int STa[maxn][20], STb[maxn][20];

void MAX_init(int n)
{
	for (int i = 0; i < n; i++)
		STa[i][0] = dfn[i + 1];
	for (int j = 1; (1 << j) <= n; j++)
	{
		for (int i = 0; i + (1 << j) - 1 < n; i++)
			STa[i][j] = max(STa[i][j - 1], STa[i + (1 << (j - 1))][j - 1]);
	}
}

void MIN_init(int n)
{
	for (int i = 0; i < n; i++)
		STb[i][0] = dfn[i + 1];
	for (int j = 1; (1 << j) <= n; j++)
	{
		for (int i = 0; i + (1 << j) - 1 < n; i++)
			STb[i][j] = min(STb[i][j - 1], STb[i + (1 << (j - 1))][j - 1]);
	}
}

int MAX(int l, int r)//[l,r)
{
	if (l >= r)
		return 0;
	int k = floor(log2(r - l));
	return max(STa[l][k], STa[r - (1 << k)][k]);
}

int MIN(int l, int r)//[l,r)
{
	if (l >= r)
		return 0;
	int k = floor(log2(r - l));
	return min(STb[l][k], STb[r - (1 << k)][k]);
}


bool cmp2(int& a, int& b)
{
	return dfn[a] < dfn[b];
}

int lca(int u, int v)
{
	while (top[u] != top[v])
	{
		if (dep[top[u]] < dep[top[v]])
			v = fa[top[v]];
		else
			u = fa[top[u]];
	}

	return dep[u] > dep[v] ? v : u;
}

void solve()
{
	tot = 0;
	Kruskal();
	for (int i = 1; i <= cntv; i++)
		hson[i] = 0;
	dfs1(cntv, 0, 1), dfs2(cntv, 0, cntv);
	MAX_init(cntv), MIN_init(cntv);
	int l, r;
	for (int i = 1; i <= Q; i++)
	{
		cin >> l >> r;
		int num = 0, ans = 0, mi = MAX(l - 1, r), mx = MIN(l - 1, r);
		ans = val[lca(rnk[mi], rnk[mx])];
		cout << ans << ' ';
	}
	cout << endl;
}

int main()
{
	IOS;
	cin >> T;
	while (T--)
	{
		int u, v;
		es.clear();
		cin >> N >> M >> Q;
		for (int i = 1; i <= N + M; i++)
			G[i].clear(), val[i] = 0;
		cntv = N, cnte = M;
		for (int i = 1; i <= M; i++)
			cin >> u >> v, es.push_back(Edge{ u,v,i });
		solve();
	}

	return 0;
}
posted @ 2022-07-21 16:04  Prgl  阅读(49)  评论(0)    收藏  举报