CERC 16
Problem F
题意:给出序列a和目标序列b.下标小的可以放到下标大的内部.每个物品内部最多直接放一个物品.a[i]!=0 则表示i放在a[i]内部.
操作1:x放入y (条件:节点y是空的(y无父节点也没前驱) && x没有父节点.)
操作2 把x从y中取出 (条件:节点y父节点.)
问将序列a变为序列b的最小操作次数? n<=1e5.
n=6 a={2,5,4,0,0,0},b={2,6,4,5,0,0};
a的嵌套方式:{1->2->5},{3->4}.
b的嵌套方式:{1->2->6},{3->4->5}.
3次操作:连接2->6 删除2->5 连接4->5.
若a[i]!=b[i] 则要想让i指向b[i]
只能先把i->a[i]->..这条链全部拆掉.
b[i]不能有直接的儿子 x->b[i]
x->b[i]已经在第一步被删除了 (第一步后i->b[i] 或者i->'0')
然后b[i]要为free b[i]->nxt->..这条链也只能全部拆掉.
7
3 5 4 0 7 0 0
3 5 0 6 7 0 0
Problem F
题意:给出序列a和目标序列b.下标小的可以放到下标大的内部.每个物品内部最多直接放一个物品.a[i]!=0 则表示i放在a[i]内部.
操作1:x放入y (条件:节点y是空的(y无父节点也没前驱) && x没有父节点.)
操作2 把x从y中取出 (条件:节点y父节点.)
问将序列a变为序列b的最小操作次数? n<=1e5.
n=6 a={2,5,4,0,0,0},b={2,6,4,5,0,0};
a的嵌套方式:{1->2->5},{3->4}.
b的嵌套方式:{1->2->6},{3->4->5}.
3次操作:连接2->6 删除2->5 连接4->5.
若a[i]!=b[i] 则要想让i指向b[i]
只能先把i->a[i]->..这条链全部拆掉.
b[i]不能有直接的儿子 x->b[i]
x->b[i]已经在第一步被删除了 (第一步后i->b[i] 或者i->'0')
然后b[i]要为free b[i]->nxt->..这条链也只能全部拆掉.
现在a[i]!=b[i]的 可以直接把i->b[i]即可 (i and b[i] are free && b[i] has no son)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,a[N],b[N],vis[N],p[N];
int main()
{
while(cin>>n)
{
int ans=0;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
for(int i=1;i<=n;i++)
p[a[i]]=i;
for(int i=1;i<=n;i++)
{
if(a[i]==b[i]) continue;
//i->a[i]->.. destroy
int y;
for(int x=i;a[x];x=y)
{
y=a[x];
a[x]=0,p[y]=0;
ans++;
}
}
//i->b[i] or i->'0'
//do:i->b[i]:only if b[i] is free (right now b[i] has no son)
for(int i=1;i<=n;i++)
{
if(a[i]==b[i]) continue;
//b[i]->nxt->.. destroy
int y;
for(int x=b[i];a[x];x=y)
{
y=a[x];
a[x]=0,p[y]=0;
ans++;
}
}
for(int i=1;i<=n;i++)
if(a[i]!=b[i]) // i and b[i] are free now
ans++;
cout<<ans<<endl;
}
return 0;
}
7
3 5 4 0 7 0 0
3 5 0 6 7 0 0