• Codeforces Round #506 (Div. 3)


    A. Many Equal Substrings

    题解:数据比较小,可以暴力。当数据有1e5时,可以利用kmp的nxt数组得到最长的相同的前缀和后缀。

    B. Creating the Contest

    ps:~

    C. Maximal Intersection

    题解:n条线段的相交部分一定是(Lmax,Rmin),那么我们可以暴力删除每一条线段,然后查询最大的左端点和最小的右端点,更新答案。multiset可以维护重复的元素!!!!

    const int N = 300005;
    
    int n;
    int l[N], r[N];
    
    multiset<int, greater<int> > L;
    multiset<int> R;
    
    int main()
    {
        sc(n);
        Rep(i, 1, n) {
            sc(l[i]), sc(r[i]);
            L.insert(l[i]);
            R.insert(r[i]);
        }
        int ans = 0;
        Rep(i, 1, n) {
            L.erase(L.find(l[i]));
            R.erase(R.find(r[i]));
            ans = max(ans, *R.begin() - *L.begin());
            L.insert(l[i]);
            R.insert(r[i]);
        }
        pr(ans);
        return 0;
    }

    D. Concatenated Multiples

    题解:正整数a,b,ab % k = 0 等价于 a * size(b) % k + b % k = k,所以可以枚举b的长度,再用map标记一下。

    ps:交换红色部分的循环顺序,就会T。(假)说明:尽量在同一个map里连续操作,避免在不同map里跳着查询。至于真正的原因,I DON'T KNOW  !!!

    inline void upd(int &x, int y) { x < y && (x = y); }
    
    const int N = 200005;
    
    LL n, k;
    LL a[N], b[N], c[N];
    
    unordered_map<int, int> sp[12];
    
    int get(LL x) {
        int cnt = 0;
        while(x) cnt++, x /= 10;
        return cnt;
    }
    
    int main()
    {
        IOS;
        
        cin >> n >> k;
        Rep(i, 1, n) {
            cin >> a[i];
            b[i] = get(a[i]);
            c[i] = a[i] % k;
            sp[b[i]][c[i]]++;
        }
    
        LL cnt = 0;
        LL tt, tp;
    
        LL p[11];
        p[1]= 10;
        Rep(i, 2, 10) p[i] = p[i - 1] * 10 % k;
    
        Rep(j, 1, 10) Rep(i, 1, n) {
    
            tp = (k - (p[j] % k * a[i]) % k);
            if (tp == k) tp = 0;
    
            tt = sp[j][tp];
    
            if (!tt) continue;
            cnt += tt;
    
            if ((b[i] == j) && (tp == c[i])) cnt--;
        }
    
        cout << cnt << endl;
        return 0;
    }

     E. Tree with Small Distances

    ps:贪心,从底向上,标记节点的父亲比标记节点更优

    const int N = 2e5;
    
    int n, pa[N];
    bool use[N];
    
    vector<int> G[N], arr;
    
    void DFS(int u = 0, int d = 0, int p = 0) {
        pa[u] = p;
        for (auto v : G[u]) if (v != p) DFS(v, d + 1, u);
        if (d > 2) arr.pb(u);
    }
    
    int main() {
    
        cin >> n;
        rep(i, 1, n){
            int u, v;
            cin >> u >> v;
            u--, v--;
            G[u].pb(v);
            G[v].pb(u);
        }
    
        DFS();
    
        int ans = 0;
        for (auto u : arr) if (!use[u]) {
            ans++;
            for (auto v : G[pa[u]]) use[v] = 1;
            use[pa[u]] = 1;
        }
    
        cout << ans << endl;
        return 0;
    }

     F. Multicolored Markers

    题解:大矩形的形状容易确定,重点在于检查其中一种颜色在当前矩形中是否能填成矩形,枚举矩形的短边,二分检查颜色a,颜色b能否组成矩形。

    inline void upd(int &x, int y) { x < y && (x = y); }
    
    const int N = 100000005;
    
    LL a, b;
    
    vector<LL> s, sa, sb;
    
    void Inite() {
    
        s.clear();
        sa.clear();
        sb.clear();
    
        LL x = a + b;
        Rep(i, 1, (int)sqrt(x)) if (x % i == 0) s.pb(i);
    
        x = a;
        Rep(i, 1, (int)sqrt(x)) if (x % i == 0) sa.pb(i);
    
        x = b;
        Rep(i, 1, (int)sqrt(x)) if (x % i == 0) sb.pb(i);
    }
    
    void Solve() {
        LL ans = INF64;
        for(auto x : s) {
    
            bool flag = 0;
    
            int pos1 = lower_bound(Range(sa), x) - sa.begin();
            int t = (sa[pos1] == x ? x : sa[pos1 - 1]);
    
            if (a / t <= (a + b) / x) flag = 1;
    
            int pos2 = lower_bound(Range(sb), x) - sb.begin();
            int o = (sb[pos2] == x ? x : sb[pos2 - 1]);
    
            if (b / o <= (a + b) / x) flag = 1;
    
            LL tp = 2 * ((a + b) / x + x);
            if (flag && tp < ans) ans = tp;
        }
        cout << ans << endl;
    }
    
    int main()
    {
        cin >> a >> b;
        Inite();
        Solve();
        return 0;
    }

     ps:有些代码写得真的很优秀

    LL a, b, c;
    set<LL> s;    // 矩形的长(长 >= 宽)的集合
    
    int main()
    {
        cin >> a >> b;
        c = a + b;
        LL ans = INF64;
        for (LL i = 1; i * i <= c; ++i) {
            if (a % i == 0 && i * i <= a) s.insert(a / i);
            if (b % i == 0 && i * i <= b) s.insert(b / i);
            if (c % i == 0 && c / i >= *s.begin()) ans = min(ans, 2 * (c / i + i));     // 保证了 a矩形的长 和 b矩形的长 都小于等于 c矩形的长   
    } cout
    << ans << endl; return 0; }
  • 相关阅读:
    jsp页面间传递参数 中文乱码问题(zz)
    java 生成xml
    java dom4j 解析xml
    生成不重复的32为随机码
    [HYSBZ
    七夕祭
    [CF741D] Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
    Baltic2014 sequence
    [洛谷P2459] SDOI2011 消耗战
    [洛谷P4172] WC2006 水管局长
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/9535125.html
Copyright © 2020-2023  润新知