Educational Codeforces Round 16

Educational Codeforces Round 16

https://codeforces.com/contest/710
4/6:ABCE

A. King Moves

#include <bits/stdc++.h>

using namespace std;
int cnt, ans;

int main () {
    char c;
    int n;
    cin >> c >> n; 
    if (c == 'h')  cnt ++;
    if (c == 'a')  cnt ++;
    if (n == 1)    cnt ++;
    if (n == 8)    cnt ++;

    if (!cnt)   ans = 8;
    else if (cnt == 1)  ans = 5;
    else if (cnt == 2)  ans = 3;
    cout << ans;
}

B. Optimal Point on a Line

#include <bits/stdc++.h>

using namespace std;
const int N = 3e5 + 5;
int a[N], n;

int main () {
    cin >> n;
    for (int i = 1; i <= n; i++)    cin >> a[i];
    sort (a + 1, a + n + 1);
    cout << a[(n+1)/2];
}

//中位数

C. Magic Odd Square

菱形构造

#include <bits/stdc++.h>

using namespace std;
const int N = 2505;
int a[N][N], n;

int main () {
    cin >> n;
    int m = n / 2 + 1;
    for (int i = 1; i <= m; i++) {
        for (int j = m - i + 1; j <= m; j++) {
            a[i][j] = a[i][n-j+1] = a[n-i+1][j] = a[n-i+1][n-j+1] = 1;
        }
    }
    
    int odd = 1, even = 2;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            //cout << a[i][j] << ' ';
            if (a[i][j])    cout << odd << ' ', odd += 2;
            else    cout << even << ' ' , even += 2;
        }
        cout << endl;
    }
}

//没看到是奇数呜呜呜
//菱形

D. Two Arithmetic Progressions

看不懂数论www

E. Generate a String

线性dp。
注意两个细节:见代码注释。

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int N = 1e7 + 5, inf = 1e18;
int n, a, b;
int f[N][3]; //选择方式

signed main () {
    cin >> n >> a >> b;
    memset (f, 0x3f, sizeof f);
    f[1][0] = a;
    for (int i = 2; i <= n; i++) {
        f[i][0] = min ({f[i-1][0], f[i-1][1], f[i-1][2]}) + a;
        //f[i][1] = min ({f[i+1][0], f[i+1][1], f[i+1][2]}) + a; //不能用未更新的状态i+1来更新i
        if (i & 1) {
            f[i][2] = min ({f[i/2+1][0], f[i/2+1][1], f[i/2+1][2]}) + b + a;
            //f[i][2] = min(f[i][2], min ({f[i/2][0], f[i/2][1], f[i/2][2]})) + b + a; //删除操作一定不会连续进行两次所以这个不优
        }
        else    f[i][2] = min ({f[i/2][0], f[i/2][1], f[i/2][2]}) + b;
    }
    //cout << f[n][0] << ' ' << f[n][1] << ' ' << f[n][2] << endl;
    cout << min({f[n][0], f[n][1], f[n][2]});
}

题解版本:

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int N = 1e7 + 5;
int n, a, b;
int f[N]; //选择方式

signed main () {
    cin >> n >> a >> b;
    memset (f, 0x3f, sizeof f);
    f[1] = a;
    for (int i = 2; i <= n; i++) {
        if (i & 1)  f[i] = min (f[(i+1)/2] + a + b, f[i-1] + a);
        else        f[i] = min (f[i/2] + b, f[i-1] + a);
    }
    cout << f[n];
}

//删除操作一定不会连续进行两次

F. String Set Queries

数据结构,字符串。

ACAM做法

二进制分组

// LUOGU_RID: 99575335
#include <bits/stdc++.h>
#define ll long long

using namespace std;
const int N = 3e5 + 5;
char s[N];

struct ACAM {
    int trans[N][26], tr[N][26], fail[N];
    int idx, tot, rt[N], sz[N];
    int que[N], cnt[N], sum[N];
    
    void insert(char s[], int& root) {
        if (!root) root = ++idx;
        int p = root;
        for (int i = 0; s[i]; i++) {
            int c = s[i] - 'a';
            if (!tr[p][c]) tr[p][c] = ++idx;
            p = tr[p][c];
        }
        cnt[p]++;
    }
    
    void build(int root) {
        int tt = -1, hh = 0;
        fail[root] = root;
        for (int i = 0; i < 26; i++) {
            if (tr[root][i]) {
                trans[root][i] = tr[root][i];
                que[++tt] = tr[root][i];
                fail[tr[root][i]] = root;
            }
            else trans[root][i] = root;
        }
        
        // 一般的ac自动机root默认为0 所以不需要特意赋fail指针
        // 但是这里需要
        
        while (hh <= tt) {
            int t = que[hh++];
            for (int i = 0; i < 26; i++) {
                int p = tr[t][i], &q = trans[t][i];
                if (!p) q = trans[fail[t]][i];
                else {
                    q = p;
                    fail[q] = trans[fail[t]][i];
                    que[++tt] = q;
                }
            }
            sum[t] = cnt[t] + sum[fail[t]];
        }
    }
    
    int merge(int& u, int& v) {
        if (!u || !v) return u | v;
        cnt[u] += cnt[v];
        for (int i = 0; i < 26; i++)    tr[u][i] = merge(tr[u][i], tr[v][i]);
        return u;
    }
    
    void insert(char s[]) {
        sz[++tot] = 1;
        rt[tot] = ++idx;
        insert(s, rt[tot]);
        while (sz[tot] == sz[tot - 1]) {
            sz[--tot] <<= 1;
            rt[tot] = merge(rt[tot], rt[tot + 1]);
        }
        build(rt[tot]);
    }
    
    ll query(char s[]) {
        int p = 0;
        ll res = 0;
        for (int i = 1; i <= tot; i++) {
            int p = rt[i];
            for (int j = 0; s[j]; j++) {
                int c = s[j] - 'a';
                p = trans[p][c];
                res += sum[p];
            }
        }
        return res;
    }
} add, del;

int main () {
    int n;
    cin >> n;
    while (n --) {
        int op;
        cin >> op >> s;
        if (op == 1)    add.insert (s);
        else if (op == 2)   del.insert (s);
        else    cout << add.query(s) - del.query(s) << endl;
    }
}

字符串哈希做法

posted @ 2023-01-13 11:44  Sakana~  阅读(23)  评论(0编辑  收藏  举报