• Educational Codeforces Round 19


    Educational Codeforces Round 19  

    A. k-Factorization

    找出所有质因子,把多的合并一下

    view code
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    
    void solve(){
        int n, k;
        cin >> n >> k;
        vector<int> vec;
        for(int i = 2; i  * i <= n; i++){
            if(n%i!=0) continue;
            while(n%i==0){
                n /= i;
                vec.push_back(i);
            }
        }
        if(n!=1) vec.push_back(n);
        if(k>vec.size()) cout << -1 << endl;
        else{
            while(vec.size() > k){
                int x = vec.back();
                vec.pop_back();
                vec.back() *= x;
            }
            for(int x : vec) cout << x << ' '; cout << endl;
        }
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    B. Odd sum

    (dp)一下,(dp[i][0])(dp[i][1])分别表示已经得到的子序列的和为偶数和奇数的情况的最大值

    view code
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    int n, A[MAXN], pre[MAXN];
    int f[MAXN][2];
    void solve(){
        ____();
        cin >> n;
        f[0][1] = -0x3f3f3f3f;
        for(int i = 1; i <= n; i++){
            int x; cin >> x;
            if(x&1){
                f[i][0] = max(f[i-1][0],f[i-1][1]+x);
                f[i][1] = max(f[i-1][1],f[i-1][0]+x);
            }else{
                f[i][0] = max(f[i-1][0],f[i-1][0]+x);
                f[i][1] = max(f[i-1][1],f[i-1][1]+x);
            }
        }
        cout << f[n][1] << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    C. Minimal string

    显然需要贪心选取最小的字母,这个用子序列自动机来做一下,同时维护一个栈,每次找到下一个最小的字母的位置,先和栈顶的字母比较,然后再把这个字母添加到答案里去,把中间中间跳过去的的字符全部加到栈里面去。

    view code
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    char s[MAXN];
    int nxt[MAXN][26];
    stack<char> stk;
    void solve(){
        cin >> s + 1;
        int n = strlen(s+1);
        for(int i = 0; i < 26; i++) nxt[n][i] = MAXN;
        for(int i = n - 1; i >= 0; i--){
            for(int j = 0; j < 26; j++) nxt[i][j] = nxt[i+1][j];
            nxt[i][s[i+1]-'a'] = i+1;
        }
        string ret;
        int ptr = 0;
        while(true){
            bool ok = false;
            for(int i = 0; i < 26; i++){
                if(nxt[ptr][i]!=MAXN){
                    while(!stk.empty() and stk.top()<=i+'a') ret += stk.top(), stk.pop();
                    ret += s[nxt[ptr][i]];
                    for(int k = ptr + 1; k < nxt[ptr][i]; k++) stk.push(s[k]);
                    ok = true;
                    ptr = nxt[ptr][i];
                    break;
                }
            }
            if(!ok) break;
        }
        while(!stk.empty()) ret += stk.top(), stk.pop();
        cout << ret << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    D. Broken BST

    从根到某个节点的路径是唯一的,所以我们可以知道从根到查询节点经过哪些点是需要走左儿子,哪些点需要走右儿子,显然走左儿子必须要满足查询节点的值比当前节点的值小,右儿子一定要查询节点的值比当前节点的值大,所以我们可以(dfd)过程中记录走左儿子的点的最小值和走右儿子的点的最大值,然后判断查询节点的值是否在可行区间内即可

    注意处理值相同的情况

    view code
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    int ls[MAXN], rs[MAXN], n, root, w[MAXN], ret;
    bool vis[MAXN];
    map<int,bool> msk;
    void dfs(int u, int mi, int ma){
        if(w[u]>=ma and w[u]<=mi) msk[w[u]] = true;
        if(ls[u]!=-1) dfs(ls[u],min(mi,w[u]),ma);
        if(rs[u]!=-1) dfs(rs[u],mi,max(ma,w[u]));
    }
    void solve(){
        ____();
        cin >> n;
        for(int i = 1; i <= n; i++){
            cin >> w[i] >> ls[i] >> rs[i];
            if(ls[i]!=-1) vis[ls[i]] = true;
            if(rs[i]!=-1) vis[rs[i]] = true;
        }
        for(int i = 1; i <= n; i++) if(!vis[i]) root = i;
        dfs(root,0x3f3f3f3f,-1);
        for(int i = 1; i <= n; i++) if(!msk.count(w[i])) ret++;
        cout << ret << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    E. Array Queries

    如果暴力(dp)复杂度会很高,复杂度高的原因是会有很多小的(k),那么我们预处理出来所有小的(k)的答案就好了

    设一个(k)上限,小于上限预处理,大于等于直接跑,选上限为(sqrt n),复杂度为(O(qsqrt n))

    view code
    //#pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 1e5+7;
    const int lim = 300;
    int n, A[MAXN], f[MAXN][lim];
    void solve(){
        ____();
        cin >> n;
        for(int i = 1; i <= n; i++) cin >> A[i];
        for(int k = 1; k < lim; k++){
            for(int i = n; i >= 1; i--){
                if(i+A[i]+k>n) f[i][k] = 1;
                else f[i][k] = 1 + f[i+A[i]+k][k];
            }
        }
        int q; cin >> q;
        while(q--){
            int p, k; cin >> p >> k;
            if(k < lim) cout << f[p][k] << endl;
            else{
                int __count = 0;
                while(p<=n) p = p+A[p]+k, __count++;
                cout << __count << endl;
            }
        }
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    

    F. Mice and Holes

    显然需要把所有老鼠和洞按位置先排序

    然后(dp[i][j])表示考虑前(i)个洞口,安排了(j)只老鼠的最小距离和

    那么转移方程就长这样:

    [dp[i][j] = min_{k}{dp[i-1][k]+S[j]-S[k]},j-k<=c_i ]

    其中(S[i])表示前(i)个老鼠到当前枚举的洞口的距离和,(c_i)表示(i)号洞口的容量

    由于转移方程中(S[j])是定值,可以用单调队列来维护

    view code
    // #pragma GCC optimize("O3")
    //#pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<bits/stdc++.h>
    using namespace std;
    function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
    const int MAXN = 5007;
    typedef long long int LL;
    int n, m, x[MAXN];
    LL f[2][MAXN], dis[MAXN];
    pair<int,int> hole[MAXN];
    pair<LL,int> que[MAXN];
    void solve(){
        ____();
        cin >> n >> m;
        for(int i = 1; i <= n; i++) cin >> x[i];
        for(int i = 1; i <= m; i++) cin >> hole[i].first >> hole[i].second;
        sort(x+1,x+1+n); sort(hole+1,hole+1+m);
        memset(f,0x3f,sizeof(f));
        int tag = 1; f[0][0] = 0;
        for(int i = 1; i <= m; i++, tag ^= 1){
            memset(f[tag],0x3f,sizeof(f[tag]));
            f[tag][0] = 0;
            int d = hole[i].first, c = hole[i].second;
            for(int j = 1; j <= n; j++) dis[j] = dis[j-1] + abs(d-x[j]);
            int head = 0, tail = -1;
            que[++tail] = {0,0};
            for(int j = 1; j <= n; j++){
                LL dp = f[tag^1][j] - dis[j];
                while(head<=tail and que[tail].first>=dp) tail--;
                que[++tail] = {dp,j};
                if(j-que[head].second>c) head++;
                f[tag][j] = que[head].first + dis[j];
            }
        }
        cout << (f[tag^1][n] < 0x3f3f3f3f3f3f3f3f ? f[tag^1][n] : -1) << endl;
    }
    int main(){
        #ifndef ONLINE_JUDGE
        freopen("Local.in","r",stdin);
        freopen("ans.out","w",stdout);
        #endif
        solve();
        return 0;
    }
    
  • 相关阅读:
    从YouTube改版看“移动优先”——8个移动优先网站设计案例赏析
    如何设计出正确的搜索模式?
    20个优秀手机界面扁平化设计,让你一秒看懂扁平化
    更巧妙的表单设计与登陆访问
    子树路径
    选拔赛-最短路
    hiho1050(树的直径)
    逆元
    hiho1303(模线性方程组)
    扩展欧几里德
  • 原文地址:https://www.cnblogs.com/kikokiko/p/13516939.html
Copyright © 2020-2023  润新知