首页 > 其他分享 >CF1706E Qpwoeirut and Vertices

CF1706E Qpwoeirut and Vertices

时间:2022-08-29 21:58:24浏览次数:46  
标签:cnt return text ll Vertices CF1706E ans Qpwoeirut Kruskal

前几天刚学 \(\text{Kruskal}\) 重构树,用到 CF 里就不会了……

对于每个询问 \((l,r)\),有以下两种情况:

  • \(l=r\),此时显然答案为 0。

  • \(l<r\)。

对于第二种情况,可以构造一个函数 \(f(i)\) 为将点 \(i\) 和 \(i-1\) 两点连通的最小边数。换句话说,就是一组 \((i-1,i)\) 的询问。

于是现在,我们的 \(ans_{(l,r)}=\max_{i=l+1}^r f(i)\)。

于是我们就需要考虑 \(f(i)\) 怎么求。

可以发现,如果对第 \(i\) 条边赋一个边权 \(w=i\),那么用 \(\text{Kruskal}\) 生成的最小生成树唯一且与原生成树相同。

于是边的编号转化为边的边权,现在 \(f(i)\) 变为求树上 \(i\) 和 \(i-1\) 路径上的最大边。

于是想到 \(\text{Kruskal}\) 重构树。

对原图加入边权后,跑出一颗 \(\text{Kruskal}\) 重构树,然后求 \(i\) 与 \(i-1\)
的 \(\text{lca}\) 的点权,就是 \(f(i)\)。

然后对于区间 \(\max\),上一个 ST 表就能解决问题。

// Problem: E. Qpwoeirut and Vertices
// Contest: Codeforces Round #809 (Div. 2)
// URL: https://codeforces.com/contest/1706/problem/E
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define f(i,a,b) for(ll i=a;i<=b;i++)
#define wt int tt=d;while(tt--)
#define py puts("Yes")
#define pn puts("No")
#define fe(i,e) for(int i=0;i<e.size();i++)
#define vi vector<ll>
inline ll rd() {
	ll x=0,f=1;
	char c=getchar();
	while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
	while(isdigit(c))x=x*10+c-'0',c=getchar();
	return x*f;
}
ll dx[4]={0,1,0,-1};
ll dy[4]={1,0,-1,0};
#define d rd()
#define pb push_back
ll qp(ll a,ll b,ll p){
	ll ans=1;while(b){
		if(b&1)ans=ans*a%p;
		a=a*a%p;b>>=1;
	}return ans;
}ll n,m,cnt,q;
vi e[200010];
ll val[200010];
struct node{ll u,v,w;}a[200010];
bool cmp(node a,node b){return a.w<b.w;}
ll fa[200010];
ll find(ll x){
	if(fa[x]==x)return x;
	return fa[x]=find(fa[x]);
}
ll f[200010][20];
ll de[200010];
ll st[200010][20];
ll lg[200010];
void dfs(ll u,ll fat){
	f[u][0]=fat;
	de[u]=de[fat]+1;
	fe(i,e[u]){
		ll v=e[u][i];
		if(v==fat)continue;
		dfs(v,u);
	}
}ll lca(ll u,ll v){
	if(de[u]<de[v])swap(u,v);
	for(int i=19;i>=0;i--)
		if(de[u]-(1<<i)>=de[v]){
			u=f[u][i];
			if(u==v)return u;
	}
	for(int i=19;i>=0;i--)
		if(f[u][i]!=f[v][i])
			u=f[u][i],v=f[v][i];
	return f[u][0];
}
int main(){
	wt{
		n=d,m=d,q=d;cnt=n;
		f(i,1,n*2)e[i].clear(),fa[i]=i,de[i]=0;
		f(i,1,m)a[i]={d,d,i};
		sort(a+1,a+m+1,cmp);
		f(i,1,m){
			ll u=a[i].u,v=a[i].v,w=a[i].w;
			if(find(u)==find(v))continue;
			val[++cnt]=w;
			u=find(u),v=find(v);
			fa[u]=cnt,fa[v]=cnt;
			e[cnt].pb(u),e[cnt].pb(v);
		}
		dfs(cnt,0);
		f(j,1,19)f(i,1,cnt)f[i][j]=f[f[i][j-1]][j-1];
		f(i,2,n)st[i][0]=val[lca(i,i-1)];
		lg[0]=-1;f(i,1,n)lg[i]=lg[i/2]+1;
		f(j,1,19)f(i,1,n)if(i+(1<<(j-1))<=n)
			st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		while(q--){
			ll l=d,r=d;
			if(l==r){printf("0 ");continue;}
			l++;
			printf("%lld ",max(st[l][lg[r-l+1]],st[r-(1<<lg[r-l+1])+1][lg[r-l+1]]));
		}puts("");
	}
	return 0;
}

标签:cnt,return,text,ll,Vertices,CF1706E,ans,Qpwoeirut,Kruskal
From: https://www.cnblogs.com/jimmywang/p/16637519.html

相关文章