Gym CERC 16 F Free Figuriness 思维+模拟

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->..这条链也只能全部拆掉.

现在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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值