题解 P3682 【[CERC2016]自由的套娃 Free Figurines】
RiverHamster · · 题解
这题主要要把套娃的拆开合并的方式模拟清楚,手动模拟一下会简单很多。
首先我们考虑一种最简单的完成任务的方法:把套娃全部拆开,然后再合并成所要求的样子,那么原来有父亲的都要拆开一次,把最后要求有父亲的都合并一次。
显然这样不是最优解,原来和现在状态都一样的,我们就不必拆开。一个例子:
假设我们要拆出
那么
我们发现,在一条链中,我们只能保留最小的一部分,其他只要有所更改,套娃更大的部分就不能保留(要拆开才能能取到里面)。因此找出每条链最小的部分就是不用拆开的部分(如这个例子中的
时间复杂度
code:
#include <cstdio>
int a[100005], b[100005];
bool ntail[100005]; //表示i不是链的结尾
int main(){
int n, ans = 0;
scanf("%d", &n);
for(int i=1; i<=n; i++){
scanf("%d", &a[i]);
ntail[a[i]] = true; //已经不是链的结尾(最小的套娃)了
if(a[i] != 0) ans++; //原始做法
}
for(int i=1; i<=n; i++){ //同上
scanf("%d", &b[i]);
ntail[b[i]] = true;
if(b[i] != 0) ans++;
}
int p;
for(int i=1; i<=n; i++){
if(!ntail[i]){ //是链尾
p = i;
while(a[p] == b[p] && a[p] != 0 && b[p] != 0){ //一直找相同(可以不拆开的)
ans -= 2; //避免2次操作
p = a[p];
}
}
}
printf("%d\n", ans);
return 0;
}
思路来自: 官方题解 BlackJack_的博客