• Educational Codeforces Round 81 (Rated for Div. 2) 题解


    过了n天补的题解:D

    AB就不用说了

    C. Obtain The String

    思路挺简单的,就是贪心,但是直接贪心的复杂度是O(|s|*|t|),会超时,所以需要用到序列自动机

    虽然名字很高端但是就是个数组啦(不过我自己想不到就是了)

    next[i][j]表示i之后第一次出现j字符的位置,用这个函数就可以把复杂度降到O(|t|)

    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N = 100010;
    char s[N], t[N];
    bool flag[30];
    int next[N][30];
    int main() {
        int cs;
        scanf("%d", &cs);
        while (cs--) {
            scanf("%s", s);
            scanf("%s", t);
            int len1 = strlen(t);
            int len2 = strlen(s);
            int l = 0, cnt = 1;
            memset(next, 0xff, sizeof(next));
            for (int i = len2 - 1; i >= 0; i--) {
                for (int j = 0; j < 26; j++)
                    next[i][j] = next[i + 1][j];
                next[i][s[i] - 'a'] = i;                 //递推式很简单
            }
            int pos = 0;
            for (int i = 0; i < len1; i++) {
                pos = next[pos][t[i] - 'a'] + 1;
                if (pos == 0) {
                    cnt++;
                    pos = next[0][t[i] - 'a'] + 1;
                    if (pos == 0) {
                        cnt = -1;
                        break;
                    }
                }
            }
            printf("%d
    ", cnt);
        }
        return  0;
    }

    D.Same GCDs

    如果知道了gcd(a, b) = gcd(a - b, b) (a > b)就是欧拉函数模板题,可惜不知道

    gcd(a, m) = gcd(a + x, m) = k

    gcd(a/k, m/k) = gcd(a/k + b, m/k) = 1

    刚好就是phi[m/k]的值

    #include <cstdio>
    using namespace std;
    
    long long gcd(long long a, long long b) {
        return (a % b == 0) ? b : gcd(b, a % b);
    }
    
    long long GetPhi(long long a) {
        long long res = a;
        for (long long i = 2; i * i <= a; i++) {
            if (a % i == 0) {
                res -= res / i;
                while (a % i == 0)
                    a = a / i;
            }
        }
        if (a > 1)    res -= res / a;
        return res;
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
            long long a, m;
            scanf("%lld %lld", &a, &m);
            long long k = gcd(a, m);
            long long ans = GetPhi(m / k);
            printf("%lld
    ", ans);
        }
        return 0;
    }
    // gcd(a, m) = gcd(a + x, m) = k
    // gcd(a/k, m/k) = gcd(a/k + b, m/k) = 1
    // phi[m/k];

    E.Permutation Separation

    令set1 <= val,set2 =val 为若在pos的位置把序列分成两半,则val:=val + 1的时候[1, pos - 1]加上val对应的cost,[pos, n - 1]就减去这个cost,这个可以用线段树维护

    然后有一个坑,把我卡在test 6了很久很久,就是val是从0开始,不是从1开始

    #include <cstdio>
    #include <algorithm>
    using namespace std;
    #define g(l, r) (l + r | l != r)
    #define o g(l, r)
    #define ls g(l, mid)
    #define rs g(mid + 1, r)
    const int N = 2 * 1e5 + 10;
    typedef long long ll;
    ll pos[N], p, w1, a[N];
    ll pre[N], minn[N << 1], mark[N << 1];
    int L, R;
    void build(int l, int r) {
        if (l == r) {
            minn[o] = pre[l];
            return ;
        }
        int mid = l + r >> 1;
        build(l, mid); 
        build(mid + 1, r);
        minn[o] = min(minn[ls], minn[rs]);
    }
    
    inline void PushDown(int l, int r) {
        if (mark[o] != 0) {    
            int mid = l + r >> 1;
            mark[ls] += mark[o];
            mark[rs] += mark[o];
            minn[ls] = minn[ls] + mark[o];
            minn[rs] = minn[rs] + mark[o];
            mark[o] = 0;
        }
    }
    
    void update(int l, int r, int val) {
        if (L > R)    return ;
        if (L <= l && R >= r) {
            minn[o] += val;
            mark[o] += val;
            return ;
        }
        PushDown(l, r);
        int mid = l + r >> 1;
        if (L <= mid)    update(l, mid, val);
        if (R > mid)    update(mid + 1, r, val);
        minn[o] = min(minn[ls], minn[rs]);
    }
    
    int main() {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            int k;
            scanf("%d", &k);
            pos[k] = i;
        }
        for (int i = 1; i <= n; i++) {
            scanf("%lld", &a[i]);
            pre[i] = pre[i - 1] + a[i];
        }
        build(1, n - 1);
        ll ans = minn[g(1, n - 1)];
        for (int i = 1; i <= n; i++) {
            L = pos[i], R = n - 1;
            update(1, n - 1, -a[pos[i]]);
            L = 1, R = pos[i] - 1;
            update(1, n - 1, a[pos[i]]);
            ans = min(ans, minn[g(1, n - 1)]);
        }
        printf("%lld", ans);
        return 0;
    }
  • 相关阅读:
    Set.prototype (Set) – JavaScript 中文开发手册
    wordpress插件 : 利用Max Mega Menu实现二级菜单的伸缩
    HTML textarea placeholder 属性
    Number.parseInt (Number) – JavaScript 中文开发手册
    Java 实例 – 获取 URL响应头的日期信息
    PHP date_default_timezone_set() 函数
    SIMD.fromInt32x4Bits (SIMD) – JavaScript 中文开发手册
    使用 mysql_random_data_load 生成随机数据
    python基本数据类型
    day02代码
  • 原文地址:https://www.cnblogs.com/cminus/p/12291878.html
Copyright © 2020-2023  润新知