1063. 永无乡

题目链接

1063. 永无乡

永无乡包含 n 座岛,编号从 1n ,每座岛都有自己的独一无二的重要度,按照重要度可以将这 n 座岛排名,名次用 1n 来表示。

某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。

如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b ,则称岛 a 和岛 b 是连通的。

现在有两种操作:

  • B x y 表示在岛 x 与岛 y 之间修建一座新桥。

  • Q x k 表示询问当前与岛 x 连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪座,请你输出那个岛的编号。

输入格式

第一行是用空格隔开的两个正整数 nm ,分别表示岛的个数以及一开始存在的桥数。

接下来的一行是用空格隔开的 n 个数,依次描述从岛 1 到岛 n 的重要度排名。

随后的 m 行每行是用空格隔开的两个正整数 aibi ,表示一开始就存在一座连接岛 ai 和岛 bi 的桥。

后面剩下的部分描述操作,该部分的第一行是一个正整数 q ,表示一共有 q 个操作,接下来的 q 行依次描述每个操作,操作的格式如上所述,以大写字母 QB 开始,后面跟两个不超过 n 的正整数,字母与数字以及两个数字之间用空格隔开。

输出格式

对于每个 Q x k 操作都要依次输出一行,其中包含一个整数,表示所询问岛屿的编号。

如果该岛屿不存在,则输出 1

数据范围

对于 20 的数据 n1000,q1000,
对于 100 的数据 n100000,mn,q300000

输入样例:

5 1 4 3 2 5 1 1 2 7 Q 3 2 Q 2 1 B 2 3 B 1 5 Q 2 1 Q 2 4 Q 2 3

输出样例:

-1 2 5 1 2

解题思路

splay,启发式合并

建立 nsplay 树,合并时用并查集维护信息,当要合并两棵 splay 树时,直接暴力将一棵 splay 树插入到另外一棵 splay 树上,可采用启发式合并,即将更小的 splay 树合并到更大的 splay 树上。注意:当合并时,将节点一个一个插入 splay 树中时,完全可以利用该节点的状态编号而不必生成新的节点编号,另外 splay 树中的状态节点编号与中序遍历表示的值的编号是相等的,且所有操作没有改变其对应的关系,所以可以直接利用状态节点编号返回查询的信息
另外,简单说下并查集中的节点与 splay 树中的节点的联系:并查集中节点表示一棵 splay 树,并查集的根节点 iroot[i] 表示 splay 树中的根节点编号,注意,iroot[i],在执行 splay(x,k) 操作时,并查集的 i 是不会变化的,而 splay 的根节点时刻发生变化,当节点的编号不会发现生变化,即 splay 的节点编号依然与中序遍历的编号对应

  • 时间复杂度:O(n+qlog2n)

代码

// Problem: 永无乡 // Contest: AcWing // URL: https://www.acwing.com/problem/content/1065/ // Memory Limit: 128 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) // %%%Skyqwq #include <bits/stdc++.h> //#define int long long #define help {cin.tie(NULL); cout.tie(NULL);} #define pb push_back #define fi first #define se second #define mkp make_pair using namespace std; typedef long long LL; typedef pair<int, int> PII; typedef pair<LL, LL> PLL; template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; } template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } const int N=1e5+5; int n,m,root[N],fa[N],a,b; struct Tr { int s[2],p,v,sz; void init(int _p,int _v) { p=_p,v=_v; sz=1; } }tr[N]; int find(int x) { return x==fa[x]?x:fa[x]=find(fa[x]); } void pushup(int u) { tr[u].sz=tr[tr[u].s[0]].sz+tr[tr[u].s[1]].sz+1; } void rotate(int x) { int y=tr[x].p,z=tr[y].p; int k=tr[y].s[1]==x; tr[z].s[tr[z].s[1]==y]=x,tr[x].p=z; tr[y].s[k]=tr[x].s[k^1],tr[tr[x].s[k^1]].p=y; tr[x].s[k^1]=y,tr[y].p=x; pushup(y),pushup(x); } void splay(int x,int k,int r) { while(tr[x].p!=k) { int y=tr[x].p,z=tr[y].p; if(z!=k) { if((tr[z].s[1]==y)^(tr[y].s[1]==x))rotate(x); else rotate(y); } rotate(x); } if(!k)root[r]=x; } void insert(int v,int r) { int u=root[r],p=0; while(u)p=u,u=tr[u].s[tr[v].v>tr[u].v]; u=v; if(p)tr[p].s[tr[v].v>tr[p].v]=u; tr[u].init(p,tr[v].v); splay(u,0,r); } void dfs(int v,int u) { if(tr[v].s[0])dfs(tr[v].s[0],u); if(tr[v].s[1])dfs(tr[v].s[1],u); insert(v,u); } int get_k(int u,int k) { while(u) { if(tr[tr[u].s[0]].sz>=k)u=tr[u].s[0]; else if(tr[tr[u].s[0]].sz+1==k)return u; else k-=tr[tr[u].s[0]].sz+1,u=tr[u].s[1]; } return -1; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) { int v; scanf("%d",&v); fa[i]=root[i]=i; tr[i].init(0,v); } while(m--) { scanf("%d%d",&a,&b); a=find(a),b=find(b); if(a!=b) { if(tr[root[a]].sz>tr[root[b]].sz)swap(a,b); dfs(root[a],b); fa[a]=b; } } scanf("%d",&m); while(m--) { char op[2]; scanf("%s%d%d",op,&a,&b); if(*op=='B') { a=find(a),b=find(b); if(a!=b) { if(tr[root[a]].sz>tr[root[b]].sz)swap(a,b); dfs(root[a],b); fa[a]=b; } } else { a=find(a); printf("%d\n",tr[root[a]].sz>=b?get_k(root[a],b):-1); } } return 0; }

__EOF__

本文作者acwing_zyy
本文链接https://www.cnblogs.com/zyyun/p/16462239.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   zyy2001  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示