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
原文地址:https://www.cnblogs.com/GoodVv/p/13326774.html