ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

SP4155

2022-02-26 21:34:54  阅读:177  来源: 互联网

标签:连通 ch return 树剖 int SP4155 define


题解里貌似没有树链剖分的写法?那蒟蒻来一发。

题目给定 \(n\) 个开始时不连通的点,每个点有点权,要求满足三个操作。

  • 判断两个输入的节点之间是否连通,如果不连通则在两点之间连边。
  • 单点修改。
  • 输出两个输入的节点之间路径长度。

因为题目没有强制在线,所以可以尝试使用离线建树,然后树剖套线段树维护。

因为要先离线把整棵树给建出来,所以先处理所有连边的操作,而维护连通性,很容易想得到并查集。

预处理之后树剖,注意这题不保证最后连通,所以对于森林中的每棵树都要跑一遍树剖。

之后就是转在线处理问题,并查集判联通,单修和查询都是裸的树剖操作。

毕竟题目没有要求 Cut 操作,所以不必用 LCT(其实是蒟蒻不会)。

时间复杂度是 \(O(nlog_2^2n)\),比 LCT 多了一个 log。

放一下蒟蒻丑陋的代码:

#include <bits/stdc++.h>
#define V e[i].v
#define g() getchar()
#define int long long
#define lc p<<1
#define rc p<<1|1
using namespace std;char RD(){char q=g();while (q<'a'||q>'z')q=g();return q;}
int rd(){int x=0,f=0;char ch=g();while(ch<'0'||ch>'9')f|=ch=='-',ch=g();while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=g();return f?-x:x;}
const int N=1e6,INF=2e9;char O;int n,m,fir[N],cnt,tp,tot,fa[N],si[N],d[N],h[N],t[N],id[N],di[N],a[N],b[N],vis[N],f[N];
struct edge{int v,nt;}e[N<<1];void into(int u,int v){e[++cnt].v=v;e[cnt].nt=fir[u];fir[u]=cnt;}
void dfs1(int u,int f){
	fa[u]=f;si[u]=1;for(int i=fir[u];i;i=e[i].nt)if(V!=fa[u]) 
	{d[V]=d[u]+1;dfs1(V,u);if(si[V]>si[h[u]])h[u]=V;si[u]+=si[V];}
}void dfs2(int u,int anc){
	t[u]=anc;id[u]=++tot;a[tot]=b[u];if(!h[u])return ;dfs2(h[u],anc);
	for(int i=fir[u];i;i=e[i].nt)if(V!=fa[u]&&V!=h[u])dfs2(V,V);
}struct tree{int l,r,z;}s[N<<2];void pushup(int p){s[p].z=s[lc].z+s[rc].z;}
void build(int p,int l,int r){s[p].l=l;s[p].r=r;if(l==r){s[p].z=a[l];return ;}int mid=(l+r)>>1;build(lc,l,mid);build(rc,mid+1,r);pushup(p);}
void update(int p,int x,int k){if(s[p].l==s[p].r){s[p].z=k;return ;}int mid=(s[p].l+s[p].r)>>1;if(x<=mid)	update(lc,x,k);else update(rc,x,k);pushup(p);}
int Q(int p,int l,int r){if(s[p].l>=l&&s[p].r<=r)return s[p].z;int mid=(s[p].l+s[p].r)>>1,val=0;if(l<=mid)val+=Q(lc,l,r);if(r>mid)val+=Q(rc,l,r);return val;}
int ask(int u,int v){
	int ans=0;while(t[u]!=t[v]){if(d[t[u]]<d[t[v]])swap(u,v);ans+=Q(1,id[t[u]],id[u]);u=fa[t[u]];}
	if(d[u]>d[v])swap(u,v);return ans+Q(1,id[u],id[v]);
}struct in{char op;int x,y;}r[N];int C(int x){return x==f[x]?x:f[x]=C(f[x]);}
signed main(){
	n=rd();for(int i=1;i<=n;i++){b[i]=rd();f[i]=i;}m=rd();
	for(int i=1,u,v;i<=m;i++){O=RD();u=rd();v=rd();if(O=='b'&&C(u)!=C(v))into(u,v),into(v,u),f[C(v)]=C(u);r[++tp].op=O;r[tp].x=u;r[tp].y=v;}
	for(int i=1,j=C(i);i<=n;i++,j=C(i))if(vis[j])continue;else	vis[j]++,dfs1(i,0),dfs2(i,i);
	build(1,1,n);for(int i=1;i<=n;i++)	f[i]=i;
	for(int i=1;i<=tp;i++){
		if(r[i].op=='b')if(C(r[i].x)!=C(r[i].y))f[C(r[i].y)]=C(r[i].x),puts("yes");else	puts("no");
		else if(r[i].op=='e')if(C(r[i].x)!=C(r[i].y))puts("impossible");else cout<<ask(r[i].x,r[i].y)<<endl;
		else update(1,id[r[i].x],r[i].y);
	}return 0;
}

标签:连通,ch,return,树剖,int,SP4155,define
来源: https://www.cnblogs.com/AIskeleton/p/15940533.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有