标签:tmp ed 查集 st seg fa vct 数组 acw4412
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" ;
}
小结:
标签:tmp,ed,查集,st,seg,fa,vct,数组,acw4412 来源: https://www.cnblogs.com/tyriis/p/16189017.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。