zoukankan      html  css  js  c++  java
  • Codeforces Round #708 (Div. 2)

    C1-k-LCM (easy version)

    分情况讨论一下

    void solve(){
        if(n & 1){
            cout << 1 << " " << (n / 2) << " " << (n / 2) << '
    ';
        }
        else if(n % 4 == 0){
            cout << (n / 2) << " " << (n / 4) << " " << (n / 4) << '
    ';
        }
        else{
            cout << 2 << " " << ((n - 2) / 2) << " " << ((n - 2) / 2) << '
    ';
        }
    }
    

    C2-k-LCM (hard version)

    转化成C1

    void solve() {
        for(int i = 1;i <= k - 3;i++){
            cout << 1 << " ";n--;
        }
        if (n & 1) {
            cout << 1 << " " << (n / 2) << " " << (n / 2) << '
    ';
        }
        else if (n % 4 == 0) {
            cout << (n / 2) << " " << (n / 4) << " " << (n / 4) << '
    ';
        }
        else {
            cout << 2 << " " << ((n - 2) / 2) << " " << ((n - 2) / 2) << '
    ';
        }
    }
    

    D-Genius

    看完官方的题解感觉挺巧妙的, 设 (f[i]) 表示以 (i) 为终点的最大得分值, 则把边按照从小到大的顺序来枚举,进行转移即可

    for(int i = 2;i <= n;i++){
        for(int j = i - 1;j >= 1;j--){
        	
        }
    }
    

    这样的枚举顺序可以保证边权 ((abs(c_i - c_j))) 严格递增

    void solve() {
        vector<ll>f;
        f.resize(n + 1, 0);
        for (int i = 2;i <= n;i++) {
            for (int j = i - 1;j >= 1;j--) {
                ll fi = f[i], fj = f[j], p = abs(s[i] - s[j]);
                if (tag[i] != tag[j]) {
                    f[i] = max(f[i], fj + p);
                    f[j] = max(f[j], fi + p);
                }
            }
        }
        cout << *max_element(f.begin(), f.end()) << '
    ';
    }
    

    E1-Square-free division (easy version)

    直接质因数分解然后次数全部模 2 ,转化为分成尽可能少的区间, 使得所有区间内的数两两各不相同,扫一遍就可以

    E-2Square-free division (hard version)

    (f[i][j]) 表示前 (i) 个数,使用了 (j) 次转变的最小段数, 设 (L[i][j]) 表示前 (i) 个数中, (i) 所属的段使用了 (j) 次转变所能到达的最左边的下标, 即 ([L[i][j], i]) 这个段使用了 (j) 次转变,且无法继续向左延申

    处理 (L) 的时候可以 (O(nk)) 处理出来, 枚举 (k) ,然后扫一遍。

    转移的时候

    for (int i = 1;i <= n;i++) {
            for (int j = 0;j <= k;j++) {
                if (j > 0)f[i][j] = f[i][j - 1];
                for (int lst = 0;lst <= j;lst++) {
                    f[i][j] = min(f[i][j], f[L[i][lst] - 1][j - lst] + 1);
                }
            }
        }
    
    #include<bits/stdc++.h>
    using namespace std;
    #define what(x) cerr << #x << " is " << x << endl;
    #define getall(x,ed) cerr << #x << ": 	";debug(x,ed);
    #define IO ios::sync_with_stdio(0);cin.tie(0);
    std::mt19937 rnd(time(0));
    template<typename T>
    void debug(T begin, T ed) {
        for (T i = begin;i != ed;i++)cout << *i << '	';cout << '
    ';
    }
    
    const int N = 1e7 + 10;
    typedef long long ll;
    
    vector<int>prime, vis, fp, A;
    void init() {
        vis.resize(N, 0);fp.resize(N, 0);
    
        for (int i = 2;i < N;i++) {
            if (!vis[i]) {
                prime.emplace_back(i);
                fp[i] = i;
            }
            for (auto& p : prime) {
                if (i * p >= N)break;
                vis[p * i] = 1;
                fp[p * i] = p;
                if (i % p == 0)break;
            }
        }
    }
    
    int T, n, k;
    
    void read_and_init() {
        cin >> n >> k;
        A.resize(n + 1, 0);
        for (int i = 1;i <= n;i++) {
            int x;cin >> x;
            A[i] = 1;
            while (x != 1) {
                int p = fp[x];
                x /= p;
                if (fp[x] == p) {
                    x /= p;
                }
                else {
                    A[i] *= p;
                }
            }
            //cout << A[i] << '
    ';
        }
    }
    unordered_map<int, int>cnt;
    void solve() {
        vector<vector<int>>f(n + 1, vector<int>(k + 1, 1e9));
        vector<vector<int>>L(n + 1, vector<int>(k + 1, 0));
    
        for (int j = 0;j <= k;j++) {
            int now = 0;
            int idx = 1;
            cnt.clear();
            for (int i = 1;i <= n;i++) {
    
                if (cnt.count(A[i]))now++;
                cnt[A[i]]++;
                //cout << i << " " << now << " " << idx << '
    ';
                //for(auto&x : cnt)cout << x.first << " : " << x.second << '
    ';
                if (now <= j)L[i][j] = idx;
                else {
                    while (idx <= i and now > j) {
                        if (cnt[A[idx]] >= 2)now--;
                        if (!--cnt[A[idx]])cnt.erase(A[idx]);
                        idx++;
                    }
                    L[i][j] = idx;
                }
                //what(L[i][j]);
            }
        }
    
        for (auto& c : f[0])c = 0;
    
        for (int i = 1;i <= n;i++) {
            for (int j = 0;j <= k;j++) {
                if (j > 0)f[i][j] = f[i][j - 1];
                for (int lst = 0;lst <= j;lst++) {
                    f[i][j] = min(f[i][j], f[L[i][lst] - 1][j - lst] + 1);
                }
            }
        }
        cout << f[n][k] << '
    ';
    
    
    }
    int main() {
        IO;
        init();
        cin >> T;
        while (T--) {
            read_and_init();
            solve();
        }
    }
    
  • 相关阅读:
    BZOJ1000 A+B Problem
    网络最大流
    树形结构
    BZOJ2521 最小生成树 最小割
    HDU5266 LCA 树链剖分LCA 线段树
    BZOJ3991 寻宝游戏 LCA 虚树 SET
    深度优先搜索DFS
    斯特林数
    Noip2017 普及 T3 Chess
    键盘自动机
  • 原文地址:https://www.cnblogs.com/sduwh/p/14555636.html
Copyright © 2011-2022 走看看