您的位置:首页 > 其它

4000 Gym CERC 16 F Free Figuriness 思维+模拟

2017-10-21 10:56 459 查看
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
,b
,vis
,p
;
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: