1 条题解

  • 0
    @ 2025-8-24 22:51:50

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar rzh123
    而我将 爱你所爱的人间 / 愿你所愿的笑颜 / 你的手我蹒跚在牵 / 请带我去明天

    搬运于2025-08-24 22:51:50,当前版本为作者最后更新于2023-10-28 07:51:14,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    因为每一列构成排列,如果给 ziz_i 加一,第 ii 列只有一个数字对应布尔值会从 00 变成 11,总共最多只会有一个 val2n1val_{2n-1}00 变成 11。没有从 11 变成 00 的。

    暴力枚举 ii11nn,每次给 ziz_i 一直加一直到 mm,如果还没有达到 ss 就到下一个 ii 继续加。比如样例就是枚举 $(0,0,0,0),(1,0,0,0),(2,0,0,0),(3,0,0,0),(3,1,0,0),(3,2,0,0),\cdots$,因为每次最多加 11,一定能枚举到恰好是 ss 的情况。一共枚举了 O(nm)O(nm) 种情况。

    现在只需要一种快速修改的方法。对于指令,ap,bpa_p,b_p 不重复,把 ppap,bpa_p,b_p 连边,构成了一个二叉树(表达式树),每次相当于修改一个叶节点,从叶节点开始一直跳父亲更新。更新时只有 00 变成 11 的,如果跳到一个节点时它已经是 11 就停止,如果更新完仍然是 00 也停止,这样每个节点只会被修改一次,修改的总复杂度 O(nm)O(nm)

    
    #include <bits/stdc++.h>
    using namespace std;
    constexpr int N=3e5+5;
    int n,m,s;
    struct Op{
        int a,b,t;
    };
    vector<int> x[N],pos[N],fa[N],val[N];
    // pos[i][j]: i 在第 j 列的第几行
    vector<Op> op[N];
    int z[N],crtcnt;
    void upd(int i){
        if(z[i]==1) return;
        int p=pos[z[i]-1][i];
        // val[p][i]: 0->1
        val[p][i]=1;
        if(n==1){
            ++crtcnt;
            return;
        }
        int u{fa[p][i]};
        for(;;u=fa[p][u]){
            if(val[p][u]) break;
            auto t=op[p][u-n];
            if(t.t==1) val[p][u]=(val[p][t.a]&&val[p][t.b]);
            else val[p][u]=(val[p][t.a]||val[p][t.b]);
            if(!val[p][u]) break;
            if(u==2*n-1){
                ++crtcnt;
                break;
            }
        }
        // printf("crtcnt=%d\n",crtcnt);
    }
    signed main(){
        scanf("%d%d%d",&n,&m,&s);
        for(int i{1};i<=m;++i){
            x[i].resize(n+3);
            op[i].resize(n+3);
            pos[i].resize(n+3);
            fa[i].resize(n*2+5);
            val[i].resize(n*2+5);
            for(int j{1};j<=2*n-1;++j){
                val[i][j]=0;
            }
        }
        for(int i{1};i<=m;++i){
            for(int j{1};j<=n-1;++j){
                int a,b,t;scanf("%d%d%d",&a,&b,&t);
                op[i][j]={a,b,t};
                fa[i][a]=fa[i][b]=n+j;
            }
        }
        for(int i{1};i<=m;++i){
            for(int j{1};j<=n;++j){
                scanf("%d",&x[i][j]);
                ++x[i][j];
                pos[x[i][j]][j]=i;
            }
        }
        for(int i{1};i<=n;++i) z[i]=1;
        for(int i{1};i<=n;++i){
            if(crtcnt==s) break;
            for(;;++z[i],upd(i)){
                if(crtcnt==s){
                    i=n+1;
                    break;
                }
                if(z[i]==m+1) break;
            }
        }
        for(int i{1};i<=n;++i){
            printf("%d%c",z[i]-1," \n"[i==n]);
        }
        return 0;
    }
    
    • 1

    信息

    ID
    9349
    时间
    1000ms
    内存
    128MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者