【题解】arc189_c Balls and Boxes

arc189_c Balls and Boxes

题意

给定 \(n\) 个位置,第 \(i\) 个位置有 \(a_i\) 个红球和 \(b_i\) 个蓝球。

再给定整数 \(x\) 和长度为 \(n\) 的排列 \(p,q\)

可以进行如下操作任意次:

  • 选择一个位置 \(i\)

  • \(i\) 位置的所有红球放到位置 \(p_i\)

  • \(i\) 位置的所有蓝球放到位置 \(q_i\)

问能否把所有球都放到位置 \(x\),如果能,输出最小操作次数。
如果不能,输出 -1

题解

知识点:动态规划。

\(i\)\(p_i\) 连有向边,就得到了红球的路径图。

同理,将 \(i\)\(q_i\) 连有向边,就得到了蓝球的路径图。

由于是排列,所以得到的图是若干个环。

容易发现,有解当且仅当所有篮球和红球都在 \(x\) 所在的那个环。

\(u\) 开始,跳 \(p_u\) 碰到的第一个 \(a_u=1\) 的位置,这是离 \(u\) 最远的红球,所以红球的路径就是从这个位置一直跳 \(p_u\) 跳到 \(u\) 组成的序列去掉 \(u\),设长度为 \(l_1\)

蓝球的处理同理,设长度为 \(l_2\)

与注意到一次操作是同时将蓝球红球同时拿出去的,要使得操作次数尽可能少,就要让蓝球红球一同操作的位置尽可能多,也就是两类球路径序列的 LCS(最长公共子序列),记为 \(res\),则答案为 \(l_1+l_2-res\)

#include<bits/stdc++.h>
using namespace std;

#define rep(i,l,r) for(int i=(l);i<=(r);++i)
#define per(i,l,r) for(int i=(r);i>=(l);--i)
#define pr pair<int,int>
#define fi first
#define se second
#define pb push_back
#define all(x) (x).begin(),(x).end()
#define sz(x) (x).size()
#define bg(x) (x).begin()
#define ed(x) (x).end()

#define N 202506
// #define int long long

int n,p[N],q[N],s,f[N];
bool a[N],b[N];
int l1,l2,a1[N],a2[N];

inline bool chk(){
    int sa=accumulate(a+1,a+1+n,0),res;
    int sb=accumulate(b+1,b+1+n,0),u;

    u=s;
    res=0;
    do{
        res+=a[u];
        u=p[u];
    }while(u!=s);

    if(res!=sa){
        return 0;
    }

    u=s;
    res=0;
    do{
        res+=b[u];
        u=q[u];
    }while(u!=s);

    if(res!=sb){
        return 0;
    }

    return 1;
}

struct bit{
    #define lb(x) (x&-x)
    int tr[N];

    inline void upd(int k,int d){
        while(k<=n){
            tr[k]=max(tr[k],d);
            k+=lb(k);
        }
    }

    inline int ask(int k){
        int ans=0;

        while(k){
            ans=max(ans,tr[k]);
            k-=lb(k);
        }

        return ans;
    }
}t;

signed main(){
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);

    cin>>n>>s;

    rep(i,1,n){
        cin>>a[i];
    }
    rep(i,1,n){
        cin>>b[i];
    }

    rep(i,1,n){
        cin>>p[i];
    }
    rep(i,1,n){
        cin>>q[i];
    }

    if(!chk()){
        cout<<"-1";
        return 0;
    }

    int u;
    bool suc;

    u=p[s];
    suc=0;
    while(u!=s){
        if(a[u]){
            suc=1;
        }

        if(suc){
            a1[++l1]=u;
        }

        u=p[u];
    }

    u=q[s];
    suc=0;
    while(u!=s){
        if(b[u]){
            suc=1;
        }

        if(suc){
            a2[++l2]=u;
        }

        u=q[u];
    }

    int ans=l1+l2;

    rep(i,1,l1){
        f[a1[i]]=i;
    }

    rep(i,1,l2){
        if(!f[a2[i]]){
            continue;
        }

        int res=t.ask(f[a2[i]])+1;
        t.upd(f[a2[i]],res);
    }

    cout<<ans-t.ask(n);

    return 0;
}
posted @ 2025-07-14 15:04  Lucyna_Kushinada  阅读(9)  评论(0)    收藏  举报