1 条题解

  • 0
    @ 2025-8-24 22:37:20

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar unputdownable
    下雨不是任何人的错。

    搬运于2025-08-24 22:37:20,当前版本为作者最后更新于2022-03-27 19:48:40,作者可能在搬运后再次修改,您可在原文处查看最新版

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

    以下是正文


    文中 kxk_xSxS_x 的定义与题目相同。

    文中所有 x,y,zx,y,z 都指人的编号,ii 都指题目的编号。


    首先考虑一个暴力:

    对于每一个题目 ii,找出会 ii 这道题的所有人,将其按会的题目数 kxk_x 从小到大排序。

    然后我们检查上述排序后相邻的两个人是否会讨论即可。

    这个暴力的正确性证明:

    因为每次被排序的人都至少会同一道题 ii,所以只要考虑是否完全包含即可。

    假设 x,y,zx,y,z 三个人会同一题 ii 并且 kxkykzk_x \leq k_y \leq k_z,那么如果 x,yx,yy,zy,z 间都不会讨论,那么必然有 SxSySzS_x \subseteq S_y \subseteq S_z,那么 x,zx,z 也必然不会讨论。

    考虑优化上述暴力。

    首先将所有人按 kxk_x 从小到大排序,依次插入。

    如果我们对于每一道题 ii 记录下会 ii 这道题的上一个人 lstilst_i,那么每次插入一个人 xx 的时候只需要检查 iSx\forall i \in S_xlstilst_ixx 会不会讨论。

    但是这样由于每一个 SxS_x 会被多次检查,复杂度仍然不对。

    随后我们发现,在遍历 SxS_x 的时候可以顺便求出 SxS_x 与所有 SlstiS_{lst_i} 的交集大小,于是我们可以直接通过交集大小是否为 klstik_{lst_i} 来判断两个集合是否完全包含,即会不会讨论。

    这样每次插入一个人的时间复杂度变为 Θ(Sx)\Theta(|S_x|)

    总体复杂度 Θ(nlogn+m)\Theta(n \log n +m),使用桶排可以去掉 log\log

    Code:

    int n;
    int k[1000006],a[1000006];
    vector <int> p[1000006];
    int cnt[1000006];
    inline void clear(vector <int> X) {
        vector <int> e;
        e.swap(X);
    }
    inline bool cmp(int x,int y) {
        return k[x]<k[y];
    }
    int vis[1000006];
    inline void work() {
        for(int i=1; i<=n; ++i) vis[i]=0;
        for(int i=1; i<=n; ++i) cnt[i]=0;
        n=read();
        for(int i=1; i<=n; ++i) {
            k[i]=read();
            clear(p[i]);
            p[i].resize(k[i]);
            for(int u=0; u<k[i]; ++u) p[i][u]=read();
            a[i]=i;
        }
        sort(a+1,a+n+1,cmp);
        for(int t=1; t<=n; ++t) {
            int i=a[t];
            if(k[i]==0) continue;
            for(int u=0; u<k[i]; ++u) {
                ++cnt[vis[p[i][u]]];
            }
            for(int u=0; u<k[i]; ++u) {
                int g=vis[p[i][u]];
                if(g!=0&&cnt[g]<k[g]&&cnt[g]<k[i]) {
                    puts("YES");
                    write(i); putchar(' '); write(g); puts("");
                    return ;
                }
            }
            for(int u=0; u<k[i]; ++u) {
                --cnt[vis[p[i][u]]];
                vis[p[i][u]]=i;
            }
        }
        puts("NO");
    }
    
    • 1

    信息

    ID
    7592
    时间
    1000ms
    内存
    512MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者