• Codeforces Round #686 (Div. 3)


    Codeforces Round #686 (Div. 3)

    A. Special Permutation

    Solution:

    偶数直接倒序,奇数将前(n - 1)个倒序,最后将1和n互换位置。

    Code:

    #include <iostream>
    using namespace std;
    
    int main()
    {
        int t; cin >> t;
        while(t--) {
            int n; cin >> n;
            if(n & 1) {
                for(int i = n - 1; i >= 2; --i) cout << i << " ";
                cout << n << " " << 1 << endl; 
            }
            else {
                for(int i = n; i >= 1; --i) cout << i << " ";
                cout << endl;
            }
        }
        return 0;
    }
    
    B. Unique Bid Auction

    Solution:

    模拟即可

    Code:

    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int maxn = 211111;
    int vis[maxn], n, a[maxn];
    
    int main()
    {
        int t; cin >> t;
        while(t--) {
            memset(vis, 0, sizeof(vis));
            cin >> n;
            for(int i = 1; i <= n; ++i) {
                cin >> a[i];
                vis[a[i]]++;
            }
            int ans = -1, mid = n + 1;
            for(int i = 1; i <= n; ++i) {
                if(vis[a[i]] == 1) {
                    if(a[i] < mid) {
                        mid = a[i];
                        ans = i;
                    }
                }
            }
            cout << ans << endl;
        }
        return 0;
    }
    
    C. Sequence Transformation

    Solution:

    先对数列去重,之后判断每个数字将数列分成几段即可

    Code:

    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    
    const int maxn = 211111;
    
    int a[maxn], n;
    vector<int> wh[maxn];
    
    int main()
    {
        ios_base::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);    
        int t; cin >> t;
        while(t--) {
            for(int i = 0; i <= n; ++i) wh[i].clear();
            cin >> n;
            int ans = n;
            for(int i = 0; i < n; ++i) cin >> a[i];
            int len = int(unique(a, a + n) - a);
            for(int i = 0; i < len; ++i) {
                wh[a[i]].push_back(i);
            }
            for(int i = 1; i <= n; ++i) {
                if(wh[i].size()) {
                    int k = wh[i].size() + 1;
                    if(wh[i][0] == 0) k--;
                    if(wh[i].back() == len - 1) k--;
                    ans = min(ans, k);
                }
            }
            cout << ans << endl;
        }
        return 0;
    }
    
    D. Number into Sequence

    Solution:

    DFS搜索因数即可。

    Code:

    #include <iostream>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    typedef long long ll;
    
    ll ans, n;
    ll arry[111], mid[111];
    
    void dfs(ll lft, ll k, ll la)
    {
        // cout << lft << " " << k << " " << la << endl;
        if(lft % la == 0) {
            mid[k] = lft;
            if(k + 1 > ans) {
                ans = k + 1;
                for(int i = 0; i < ans; ++i) {
                    arry[i] = mid[i];
                }
            }
        }
        for(ll i = la; i * i <= lft; i += la) {
            if(lft % i == 0 && i > 1) {
                mid[k] = i;
                dfs(lft / i, k + 1, i);
            }
        }
        return;
    }
    
    int main()
    {
        int t; cin >> t;
        while(t--) {
            cin >> n;
            ans = 0;
            dfs(n, 0, 1);
            cout << ans << endl;
            for(int i = 0; i < ans; ++i) cout << arry[i] << " ";
            cout << endl;
        }
        return 0;
    }
    
    E. Number of Simple Paths

    Solution:

    有n个节点的无向图,图中有n条边,因为对于无向图,如果有(n-1)条边,那么这个图可以看成一棵树(无自环和重边),显然此题描述的图是在树的基础上增加了一条边,这样会产生一个环,而新的图就可以看成为一个环和环上所连的几棵树,知道了这个结构我们就可以分块计算简单路径数,对于一棵有(cnt)个节点的树,因为每两点之间只有一条路径,因此该树中有(frac{cnt*(cnt-1)}{2})条边,而对于与不同的两棵树,在这个图中会有两条路径可相互到达(因为中间经过一个环),因此位于不同树上的点都有两条路径可达,因此计算点的组合即可(cnt1*cnt2),因为环上的点被计算进了树中(根节点),所以不再需要单独计算。

    Code:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <queue>
    #include <cstring>
    using namespace std;
    
    const int maxn = 211111;
    
    int vis[maxn], n, deg[maxn];
    vector<int> mp[maxn];
    vector<int> circle;
    long long ans;
    
    void topsort()
    {
        queue<int> box;
        for(int i = 1; i <= n; ++i) {
            if(deg[i] == 1) {
                box.push(i);
                deg[i]--;
            }
        }
        while(!box.empty()) {
            int fr = box.front(); box.pop();
            for(auto k : mp[fr]) {
                deg[k]--;
                if(deg[k] == 1) {
                    box.push(k);
                    deg[k]--;
                }
            }
        }
        for(int i = 1; i <= n; ++i) {
            if(deg[i] > 1) {
                circle.push_back(i);
                vis[i] = 1;
            }
        }
        return;
    }
    
    int getSize(int root)
    {
        int ans = 1;
        queue<int> box; box.push(root);
        while(!box.empty()) {
            int fr = box.front(); box.pop();
            for(auto k : mp[fr]) {
                if(vis[k] == 0) {
                    box.push(k);
                    ans++;
                    vis[k] = 1;
                }
            }
        }
        return ans;
    }
    
    int main()
    {
        int t; cin >> t;
        while(t--) {
            cin >> n;
            memset(vis, 0, sizeof(vis));
            memset(deg, 0, sizeof(deg));
            circle.clear();
            for(int i = 0; i <= n; ++i) mp[i].clear();
            for(int i = 0; i < n; ++i) {
                int u, v; cin >> u >> v;
                mp[u].push_back(v); mp[v].push_back(u);
                deg[u]++; deg[v]++;
            }
            ans = 0;
            long long sum = 0;
            topsort();
            for(auto k : circle) {
                long long cnt = getSize(k);
                // cout << k << "**" << cnt << endl;
                ans += 1LL * (cnt * (cnt - 1) / 2 + sum * cnt * 2);
                sum += 1LL * cnt;
            }
            cout << ans << endl;
        }
        return 0;
    }
    /* 
    1
    11
    9 1
    1 2
    7 1
    4 10
    8 5
    4 6
    4 2
    7 5
    2 5
    3 1
    11 6 
    */
    
    F. Array Partition

    Solution:

    因为是将数列分为三块,分别取(max)(min)(max),所以当枚举第一个位置后,后面的一个位置的从左到右会导致(min)(max)均递减,所以是单调的,因此可以用二分的方法枚举第二个合法位置,只要美剧到一个合法位置即可输出,因为会反复计算区间最值,所以可以用线段树,RMQ等数据结构维护区间最值。

    Code:

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    
    const int maxn = 411111;
    
    int a[maxn], pmx[maxn], bmx[maxn], dp[maxn][20], n;
    
    int findmin(int l, int r)
    {
        int k = 0;
        while((1 << (k + 1)) <= (r - l + 1)) {
            k++;
        }
        return min(dp[l][k], dp[r - (1 << k) + 1][k]);
    }
    
    int main()
    {
        int t; cin >> t;
        while(t--) {
            cin >> n;
            for(int i = 1; i <= n; ++i) {
                cin >> a[i];
                pmx[i] = max(a[i], pmx[i - 1]);
            }
            for(int i = 1; i <= n; ++i) {
                bmx[i] = max(bmx[i - 1], a[n - i + 1]);
                dp[i][0] = a[i];
            }
            for(int j = 1; (1 << (j - 1)) <= n; ++j) {
                for(int i = 1; i <= n; ++i) {
                    dp[i][j] = min(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
                }
            }
            bool fl = false;
            for(int i = 1; i + 2 <= n; ++i) {
                int l = i + 1, r = n - 1;
                while(l <= r) {
                    int mid = (l + r) >> 1;
                    int k = findmin(i + 1, mid);
                    int s = bmx[n - mid];
                    if(k > pmx[i] || s > pmx[i]) {
                        l = mid + 1;
                    }
                    else if(k < pmx[i] || s < pmx[i]) {
                        r = mid - 1;
                    }
                    else {
                        cout << "YES" << endl;
                        cout << i << " " << mid - i << " " << n - mid << endl;
                        fl = true;
                    }
                    if(fl) break;
                }
                if(fl) break;
            }
            if(!fl) cout << "NO" << endl;
        }
        return 0;
    }
    
  • 相关阅读:
    [转]Linq使用心得——SelectMany替代二重foreach循环
    设计模式—装饰者模式
    设计模式—桥接模式
    iOS_autoLayout_Masonry
    排序算法
    h.264硬件解码
    FFmpegh.264解码
    AAC编解码
    socket UDP简单通讯
    socket TCP简单通讯
  • 原文地址:https://www.cnblogs.com/LeafLove/p/14038007.html
Copyright © 2020-2023  润新知