• 2022牛客暑期多校训练营9(总结+补题)


    总结:

    今天这把多校,一开始签了A之后,发现G是个回文自动机的简单题,我去学了一个小时之后把这道题A了,队友1也学了一个多小时后把B的概率dp A了,接下来就来到了罚坐时间,队友2看一直没什么人做的C但是没写出来,最后大家一起写E,写到最后发现题读假了,3题结束。

    题解

    A - Car Show

    题意:

    给你一个由 m m m 种数组成的序列 a i ( 1 ≤ i ≤ n ) a_i(1\le i\le n) ai(1in) ,问有多少个区间满足区间内的数字种数为 m m m

    做法:

    双指针,维护左右区间内数字的种数,若 l , r l,r l,r 区间内数字种数为 m m m ,则对答案的贡献为 n − r + 1 n-r+1 nr+1

    代码:

    /*
     author:wuzx
     */
    
    #include
    #define ll long long
    #define int long long
    #define endl "\n"
    #define P pair<int,int>
    #define f first
    #define s second
    using namespace std;
    const int inf = 0x3f3f3f3f;
    int t;
    int n,m,k;
    const int maxn =100010;
    int a[maxn],vis[maxn];
    signed main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        cin>>n>>m;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        int l=1,r=0;
        int num=0;
        int ans=0;
        while(1)
        {
            while(num<m&&r<n)
            {
                r++;
                if(!vis[a[r]])
                    num++;
                vis[a[r]]++;
            }
            if(num!=m)
                break;
            while(num==m)
            {
                ans+=n-r+1;
                if(vis[a[l]]==1)
                    num--;
                vis[a[l++]]--;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    G - Magic Spells

    题意:

    给你 k k k 个字符串,问这 k k k 个字符串中本质不同的公共回文字符串有多少种

    做法:

    考虑使用回文自动机来解决问题,我们知道回文自动机中的每个状态都表示了单独的一个字符串的回文子串,我们可以对 k k k 个字符串建回文自动机,然后同时对他们进行 d f s dfs dfs ,若能同时更新状态,则答案 +1并继续往下搜,反之则停止搜索。

    代码:

    /*
     author:wuzx
     */
    
    #include
    #define ll long long
    using namespace std;
    const int inf = 0x3f3f3f3f;
    int t;
    int n,m,k;
    struct PAM{
        int sz,tot,last;
        string ss;
        struct node{
            int cnt = 0,fail = 0,len;
            // unordered_map ch;
            array<int,26> ch;
        };
        vector<node> st;
        int node(int l)
        {
            sz++;
            st.emplace_back();
            st[sz].len = l;
            // memset(st[sz].ch,0,sizeof st[sz].ch);
            return sz;
        }
        void init()
        {
            sz = -1;
            last = 0;
            tot = 0 ;
            ss='$';
            node(0);
            node(-1);
            st[0].fail = 1;
        }
        int getfail(int x)
        {
            while(ss[tot - st[x].len - 1] != ss[tot])
                x = st[x].fail;
            return x;
        }
        void insert(char c)
        {
            ss += c;
            tot++;
            int now = getfail(last);
            if(!st[now].ch[c-'a'])
            {
                int x = node(st[now].len + 2);
                st[x].fail = st[getfail(st[now].fail)].ch[c-'a'];
                st[now].ch[c-'a'] = x;
            }
            last = st[now].ch[c-'a'];
            st[last].cnt++;
        }
    };
    signed main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        cin>>k;
        string ss;
        PAM p[k];
        for(int i=0;i<k;i++)//输入字符串、建自动机
        {
            cin>>ss;
            p[i].init();
            for(auto c:ss)
                p[i].insert(c);
        }
        vector<int> a(k,0),b(k,1);
        int ans=0;
        function<void(vector<int>&)> dfs = [&](vector<int> &idx)
        {
            for(int i=0;i<26;i++)
            {
                int flag=1;
                vector<int> f1(k,0);
                for(int j=0;j<k;j++)
                {
                    f1[j]=p[j].st[idx[j]].ch[i];
                    flag&=(bool)f1[j];
                }
                if(flag)
                {
                    ans++;
                    dfs(f1);
                }
            }
        };
        dfs(a);//偶数长度回文串
        dfs(b);//奇数长度回文串
        cout<<ans<<endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97

    E - Longest Increasing Subsequence

    题意:

    构造一个长度为 n n n 的排列,满足排列中最长上升子序列的个数为 m m m n ≤ 100 n\le100 n100

    做法:

    使用二进制构造的方法,例如 2143657 2143657 2143657 2 3 = 8 2^3=8 23=8 个, 5216437 5 2 1 6 4 3 7 5216437 2 2 + 2 1 + 2 0 = 7 2^2+2^1+2^0=7 22+21+20=7

    代码:

    /*
     author:wuzx
     */
    
    #include
    #define ll long long
    #define int long long
    #define endl "\n"
    #define P pair<int,int>
    #define f first
    #define s second
    using namespace std;
    typedef unsigned long long ull;
    const int maxn = 200010;
    const int inf = 0x3f3f3f3f;
    const int mod = 998244353;
    int t;
    int n,m,k;
    signed main()
    {
        ios::sync_with_stdio(0);
        cin.tie(0); cout.tie(0);
        cin>>t;
        while(t--)
        {
            cin>>n;
            vector<int> a;
            while(n)
            {
                if(n&1)
                    a.emplace_back(1);
                else
                    a.emplace_back(0);
                n/=2;
            }
            int sz=a.size();
            vector<int> ans;
            for(int i=1;i<=sz-1;i++)
            {
                ans.emplace_back(i*2);
                ans.emplace_back(i*2-1);
            }
            int num=1,ma=sz*2-1;
            ans.emplace_back(-1);
            for(int i=sz-1;i>=0;i--)
            {
                if(a[i]==1)
                {
                    int pos=i*2;
                    int nb=sz-i-num;
                    for(int j=0;j<nb;j++)
                        ans.insert(ans.begin()+pos,-1);
                    num+=nb;
                }
            }
            for(auto &x:ans)
                if(x==-1)
                    x=ma++;
            cout<<ans.size()<<endl;
            for(int x:ans)
                cout<<x<<" ";
            cout<<endl;
        }   
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
  • 相关阅读:
    人工神经网络(ANN)相关介绍
    python实现Map+函数式接口替换多级if-else结构
    Azure DevOps构建CICD流水线
    计算机毕业设计(附源码)python疫情社区管理系统
    618大促:手机品牌“神仙打架”,高端市场“谁主沉浮”?
    Windows AD共享权限管理工具
    统计单词
    什么时候去检测大数据信用风险比较合适?
    通过 Grafana 对prometheus 监控做可视化
    面试字节跳动java岗被算法吊打,60天苦修这些笔记,侥幸收获offer
  • 原文地址:https://blog.csdn.net/m0_51028279/article/details/126375725