zoukankan      html  css  js  c++  java
  • 2020牛客暑期多校训练营(第一场)AFG

    A.B-Suffix Array

    题目链接

    想法:

    给你串a,先求出整个串的b数组

    a的任意后缀的b数组有个特点是:

    第一次出现‘a’ 的下标是posa , 第一次出现 'b'的posb , 一定有:

    ①:b[posa] = b[posb] = 0 ,

    ②:b[posa + 1  ~ posb - 1] = 1 (下标 posa + 1 到 posb - 1 (或[posb + 1 , posa - 1])之间的b数组的值一定为 1)

    把所有的后缀的b数组分成两部分:

    第一部分:类似 011...110 (00和0111也算)

    第二部分:第二个0之后的所有部分 (如果是01111 ,那么这项为空,也就是置为0)

    然后进行排序:

    第一关键字:如果 第一个0 和 第二个0 相差的越多 ,也就是第二个0出现的越晚 ,也就是第一部分越长 , 这个后缀的b就大

    第二关键字:如果 第一个0 和 第二个0 相差的一样大 , 那就比较第二部分

    第二部分怎么比较:

    后缀数组:可以对后缀进行排序 ,给他一个char数组s,他就会给你一个 每个后缀的名次 和 后缀的排行榜  -> rank数组和sa数组

    所以先用后缀数组把b数组的后缀排名都求出来

    然后  两个不同的后缀 就可以 o(1)进行比较了

    所以步骤就是:

    ① 把char a[] 先整个求出 b[]

    ② for 循环一遍 , 找到 当前位置开始的后缀  第一次出现'a'和'b'的位置

    ③ b数组过一遍 后缀数组 , 得到每个后缀的排名 和 第i个后缀排第几

    ④ 进行排序 , 优先排 011...110 的部分 如果相同 排第二个0之后的  那段后缀

    ⑤ 排序完输出结果

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =  1e5 + 10;
    char ch[maxn];
    char s[maxn];
    int sa[maxn],rk[maxn],tp[maxn],tax[maxn];
    int n,m,p;
    void SA_Sort(){for(int i=0;i<=m;i++){tax[i]=0;}for(int i=1;i<=n;i++){tax[rk[i]]++;}
    for(int i=1;i<=m;i++){tax[i]+=tax[i-1];}for(int i=n;i>=1;i--){sa[tax[rk[tp[i]]]--]=tp[i];}}
    void getsa(){m=n;for(int i=1;i<=n;i++){rk[i]=s[i],tp[i]=i;}SA_Sort();for(int k=1;k<=n;k<<=1)
    {p=0;for(int i=n-k+1;i<=n;i++){tp[++p]=i;}for(int i=1;i<=n;i++){if(sa[i]>k){tp[++p]=sa[i]-k;}}
    SA_Sort();for(int i=1;i<=n;i++){tp[i]=rk[i];}rk[sa[1]]=p=1;for(int i=2;i<=n;i++){
    if(tp[sa[i]]==tp[sa[i-1]]&&tp[sa[i]+k]==tp[sa[i-1]+k]){rk[sa[i]]=p;}else{p++;rk[sa[i]]=p;}}
    if(p==n)break;m=p;}}///s数组
    struct node
    {
        int pre , nex;
    };
    node ans[maxn];
    bool cmp(node t , node tt)
    {
        if(t.nex - t.pre == tt.nex - tt.pre)return rk[t.nex + 1] < rk[tt.nex+ 1];
        return t.nex - t.pre < tt.nex - tt.pre;
    }
    signed main()
    {
        while(~scanf("%d" , &n)){
            scanf("%s" , ch + 1);
            int aa = -1 , bb = -1;
            for(int i = 1 ; i <= n ; i ++){
                if(ch[i] == 'a'){
                    if(aa == -1) s[i] = 0;
                    else s[i] = i - aa;
                    aa = i;
                }
                else{
                    if(bb == -1)s[i] = 0;
                    else s[i] = i - bb;
                    bb = i;
                }
            }
            getsa();
            rk[n + 1] = -1 , rk[n + 2] = -2;
            aa = n + 1  , bb = n + 1;
            for(int i = n ; i >= 1 ; i --){
                if(ch[i] == 'a')aa = i , ans[i].pre = i , ans[i].nex = bb;
                else bb = i , ans[i].pre = i , ans[i].nex = aa;
            }
            sort(ans + 1 , ans + 1 + n , cmp);
            for(int i = 1 ; i <= n ; i ++) printf("%d ",ans[i].pre);
            printf("
    ");
        }
        return 0;
    }
    View Code

     

    F . Infinite String Comparision

    题目链接

    想法:

      延伸到两倍同等长度,比较大小

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =  2e6 + 10;
    #define ll long long
    #define ios std::ios::sync_with_stdio(false)
    const ll INF(0x3f3f3f3f3f3f3f3fll);
    const int inf(0x3f3f3f3f);
    #define int long long
    char a[maxn] , b[maxn];
    signed main()
    {
        //ios,cin.tie(0);
        while(cin >> a >> b){
            int la = strlen(a) , lb = strlen(b);
            int maxx = 2 * max(la , lb);
            int ok = 0;
            for(int i = 0 ; i < maxx ; i ++){
                if(a[i % la] > b[i % lb]){
                    ok = 1;break;
                }
                if(a[i % la] < b[i % lb]){
                    ok = 2;break;
                }
            }
            if(ok == 0){
                cout << '=' << '
    ';
            }
            else if(ok == 1){
                cout << '>' << '
    ';
            }
            else if(ok == 2){
                cout << '<' << '
    ';
            }
    
        }
        return 0;
    }
    View Code

     

    J.Easy Integration

    题目链接

     

    结论:

     推导过程:

     

     

     

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn =  1e6 + 10;
    #define ll long long
    #define ios std::ios::sync_with_stdio(false)
    #define int long long
    ll pow_mod(ll x,ll n,ll mod){ll res=1;while(n){if(n&1)res=res*x%mod;x=x*x%mod;n>>=1;}return res;}//xµÄn´Î·½mod
    const int mod = 998244353;
    unsigned ll nn[2 * maxn + 1];
    signed main()
    {
        //ios,cin.tie(0);
        nn[1] = 1;
        for(int i = 2 ; i < 2 * maxn ; i ++){
            nn[i] = nn[i - 1] * i;
            nn[i] %= mod;
        }
        unsigned ll n;
        while(cin >> n){
            cout << (nn[n] * nn[n] % mod * pow_mod(nn[n * 2 + 1] , mod - 2 , mod)) % mod << '
    ';
        }
        return 0;
    }
    View Code
  • 相关阅读:
    cds.data:=dsp.data赋值有时会出现AV错误剖析
    iOS -- 十进制、十六进制字符串,byte,data等之间的转换
    iOS -- 原生NSStream实现socket
    CA认证原理以及实现(下)
    CA认证原理以及实现(上)
    android -- 存储byte
    iOS -- 字符串(NSString *)转uint8_t的两种方法
    Android -- AsyncTask 使用和缺陷
    Swift oc 混编
    Android -- native关键字
  • 原文地址:https://www.cnblogs.com/GoodVv/p/13326774.html
Copyright © 2011-2022 走看看