acw4412. 构造数组-区间合并or并查集
4412. 构造数组-区间合并or并查集
题目大意:
有两个数列,给数列a和b,a已知,b未知。若ai==aj则表示在b数列中[i,j]区间所有数相等。现在b[0]=0,问b数组有多少种可能。
思路和代码:
比较好想,只要看a有几个区间,答案就是2^(x-1)。
这题给出两种做法,区间合并和并查集
//区间合并做法
/*
先对所有区间按照左端点排序,再去合并
合并时有三种情况:
now: s----------e
1===> l---r
2===> l-------------r
3===> l-----r
其中情况1和情况2只要更新e值,情况3要更新整个区间。
*/
void merge(vct<pll> &seg){
vct<pll> res ;
sort(seg.begin() , seg.end()) ;
ll st = -2e9 , ed = -2e9 ;
for(auto s : seg){
if(ed < s.fi){
res.pb({st , ed}) ;
st = s.fi ;
ed = s.se ;
}else ed = max(ed , s.se) ;
}
seg = res ;
}
void solve3(){
ll n ;
cin >> n ;
map<ll , ll> st , ed ;
vct<ll> num ;
rep(i , 1 , n){
ll tmp ; cin >> tmp ;
if(!st[tmp]){
num.pb(tmp) ;
st[tmp] = i ;
ed[tmp] = i ;
}else ed[tmp] = i ;
}
vct<pll> seg ;
for(auto it : num){
seg.pb({st[it] , ed[it]}) ;
}
merge(seg) ;
cout << quick_pow(2 , seg.size() - 1 , 998244353) ;
}
//并查集做法
/*
将一个区间所有点放到其右端点
注意 1xxx2xxx1xx2 是一个区间的特殊情况
*/
int find(int u , vct<int> &fa){
return fa[u] = fa[u] == u ? u : find(fa[u] , fa) ;
}
aisle
void solve2(){
cin >> n ;
vct<int> fa(n + 1 , 0) ;
vct<int> a(n + 1 , 0) ;
vct<int> nxt(n + 1 , 0) ;
map<ll , int> pre ;
rep(i , 1 , n) cin >> a[i] ;
rep(i , 1 , n) fa[i] = i ;
drep(i , 1 , n){
if(!pre[a[i]]){
pre[a[i]] = i ;
}else{
nxt[i] = pre[a[i]] ;
pre[a[i]] = i ;
}
}
ll num = n ;
int i = 1 ;
while(i <= n){
if(!nxt[i]) i ++ ;
else{
int j = i ;
while(j < nxt[i]){
if(nxt[j] > nxt[i]){
break ;
}else{
int fj = find(j , fa) ;
int fni = find(nxt[i] , fa) ;
if(fj == fni) continue ;
num -- ;
fa[fj] = fni ;
}
j ++ ;
}
i = j ;
}
}
cout << quick_pow(2 , num - 1 , 998244353) << "\n" ;
}
小结:
标签:
并查集
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· Apache Tomcat RCE漏洞复现(CVE-2025-24813)