1 条题解

  • 1
    @ 2022-8-23 17:13:37

    意识流题解,学习可以参照其他题解,此题解仅思考过程。

    或者直接看代码。


    显然出题人给你个老长的字符串压位了信息,可见这题要超级高效地解决才行。

    于是首先先把四个四个四个压位出来的值离散化。

    然后“基因比较”就变成了数字匹配。

    注意到本题中 n=m=l2n=m=l^2l130l\le130,数据随机。

    考虑 Hash。

    把值域按 22 分块,则在数据完全随机且较大时,有较大概率,会出现某几块同源虫都存在的现象。

    于是直接暴力枚举每个块内匹配。

    然后暴力匹配判断,成功率会有增加。


    然后你发现假了。

    改一改。

    把值域按 11 分块,则在数据完全随机且较大时,有较大概率,会出现某 L/2L/2 块同源虫都存在的现象。

    对每个数,仅保留前 55 块。

    于是直接暴力枚举每个块内匹配。

    这个东西就正确了。

    但复杂度点名被卡了。


    匹配复杂度是 O(l)O(l) 的?

    似乎无法优化了?

    询问是 O(n)O(n) 组的?

    似乎也无法优化了?

    因此我们要做到平均 O(1)O(1) 分配。


    考虑最开始那种方法。

    改为分成 L/21L/2-1 块,其中必有某块匹配了至少两个。

    暴力枚举是哪块,再枚举是哪两个,就好了。

    可以证明,此时复杂度得到保障。


    Code

    为了方便,这里改为分成 L/2L/2 块。这样成功率仍旧很高。

    #include <algorithm>
    #include <random>
    #include <stdio.h>
    #include <vector>
    typedef long long llt;
    typedef unsigned uint;typedef unsigned long long ullt;
    typedef bool bol;typedef char chr;typedef void voi;
    typedef double dbl;
    template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;}
    template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;}
    template<typename T>T lowbit(T n){return n&-n;}
    template<typename T>T gcd(T a,T b){return b?gcd(b,a%b):a;}
    template<typename T>T lcm(T a,T b){return(a!=0||b!=0)?a/gcd(a,b)*b:(T)0;}
    template<typename T>T exgcd(T a,T b,T&x,T&y){if(b!=0){T ans=exgcd(b,a%b,y,x);y-=a/b*x;return ans;}else return y=0,x=1,a;}
    template<typename T>T power(T base,T index,T mod)
    {
        T ans=1%mod;
        while(index)
        {
            if(index&1)ans=ans*base%mod;
            base=base*base%mod,index>>=1;
        }
        return ans;
    }
    typedef unsigned short u16;
    namespace Turn
    {
        std::vector<std::pair<u16,u16> >Map[70005];u16 cnt;
        u16 get(uint v){
            u16 u=v>>16,d=v&65535;
            for(auto s:Map[u])if(s.first==d)return s.second;
            return Map[u].push_back({d,cnt}),cnt++;
        }
        uint turn(chr*c){return(uint)c[0]<<24|(uint)c[1]<<16|(uint)c[2]<<8|(uint)c[3];}
    }
    chr C[20000005];u16 Info[40005][135];
    bol Gone[40005];uint Another[40005],l;
    bol check(uint u,uint v)
    {
        if(u==v)return false;
        static uint User[265];std::merge(Info[u],Info[u]+l,Info[v],Info[v]+l,User);
        uint ans=0;for(uint i=1;i<l*2;i++)ans+=User[i-1]==User[i];
        return ans==l/2;
    }
    uint R[40005];
    std::vector<uint>A[265][265];
    int main()
    {
    #ifdef MYEE
        freopen("QAQ.in","r",stdin);
        // freopen("QAQ.out","w",stdout);
    #endif
        uint n,m;scanf("%u%u%u%s",&n,&m,&l,C);
        for(uint i=0;i<n*2;i++)for(uint j=0;j<l;j++)Info[i][j]=Turn::get(Turn::turn(C+((i*l+j)<<2)));
        for(uint i=0;i<n*2;i++)std::sort(Info[i],Info[i]+l);
        for(uint i=0;i<l/2;i++)
        {
            for(uint j=0;j<l*2;j++)for(uint k=j+1;k<l*2;k++)A[j][k].clear();
            for(uint j=0;j<n*2;j++)if(!Gone[j])
            {
                uint a=R[j];uint&r=R[j];while(r<l&&Info[j][r]<(i+1)*l*2)r++;
                while(a<r)
                {
                    for(uint k=a+1;k<r;k++)A[Info[j][a]%(l*2)][Info[j][k]%(l*2)].push_back(j);
                    a++;
                }
            }
            for(uint j=0;j<l*2;j++)for(uint k=j+1;k<l*2;k++)
                for(auto x:A[j][k])if(!Gone[x])for(auto y:A[j][k])if(!Gone[y]&&check(x,y))
                {
                    Gone[x]=Gone[y]=true,Another[x]=y,Another[y]=x;break;
                }
        }
        for(uint x=0;x<n*2;x++)if(!Gone[x])for(uint y=x+1;y<n*2;y++)if(!Gone[y]&&check(x,y))
        {
            Gone[x]=Gone[y]=true,Another[x]=y,Another[y]=x;break;
        }
        for(uint i=0;i<n*2;i++)printf("%u\n",Another[i]+1);
        return 0;
    }
    
    • 1

    信息

    ID
    3820
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    (无)
    递交数
    3
    已通过
    2
    上传者