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

    传送门

    A. Happy Birthday, Polycarp!

    签到。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/14 19:07:57
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    int n;
     
    void run(){
        cin >> n;
        int x = n;
        int tot = 0;
        while(x) {
            ++tot; x /= 10;
        }   
        int ans = 0;
        for(int i = 1; i <= 9; i++) {
            ans += tot - 1;
            if(tot != 10) {
                int now = 0;
                for(int j = 1; j <= tot; j++) now = now * 10 + i;
                if(now <= n) ++ans;
            }
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    B. Make Them Odd

    用一个set从大到小模拟一下这个过程即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/14 19:13:49
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    set <int> S;
     
    void run(){
        int n; cin >> n;
        for(int i = 1; i <= n; i++) {
            int x; cin >> x;
            if((x & 1) == 0) S.insert(x);
        }
        int ans = 0;
        while(!S.empty()) {
            auto it = S.end(); --it;
            int now = *it; 
            S.erase(it);
            now >>= 1;
            if((now & 1) == 0) S.insert(now);
            ++ans;
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    C. As Simple as One and Two

    题意:
    给出一个串(s),现在要删除最少的字符,使得串中不含(one,two)

    思路:
    直接的想法就是找到(one,two)就删除,但这里可能有个问题:比如(twoone、tttwo)这种,显然有较优的删除方法。
    对于有单词重复的情况,显然我们删除一个(w)和一个(n)最优(因为只可能在两边重复)。
    对于两个单词连接起来的情况,我们删除一个(o)最优。
    所以分情况讨论即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/14 19:26:17
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5;
     
    char s[N];
    int del[N];
     
    bool chk1(int p) {
        return s[p] == 'o' && s[p + 1] == 'n' && s[p + 2] == 'e';  
    }
     
    bool chk2(int p) {
        return s[p] == 't' && s[p + 1] == 'w' && s[p + 2] == 'o';   
    }
     
    void run(){
        cin >> (s + 1);
        int n = strlen(s + 1);
        for(int i = 1; i <= n; i++) del[i] = 0;
        for(int i = 1; i <= n - 2; i++) {
            if(chk2(i)) {
                if(i + 3 <= n && s[i + 3] == 'o') del[i + 1] = 1;
                else del[i + 2] = 1;
            }   
            if(chk1(i)) {
                if(i - 1 >= 1 && s[i - 1] == 'o') del[i + 1] = 1;
                else del[i] = 1;   
            }
        }
        int ans = 0;
        for(int i = 1; i <= n; i++) ans += del[i];
        cout << ans << '
    ';
        for(int i = 1; i <= n; i++) if(del[i]) cout << i << ' ';
        cout << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    D. Let's Play the Words?

    题意:
    给出若干个互不相同(01)串,问最少翻转多少次,满足:

    • 所有串互不相同
    • 存在一种方案,使得串能够拼接起来

    这里的拼接不要求形成环,而是线性拼接起来,只要头尾相同即可拼接,并且我们可以任意安排顺序。

    思路:
    之后所说的(xy)串指的是头为(x),尾为(y)的串。

    • 首先注意到我们翻转(00,11)串没用,我们可以只关注(01,10)串。
    • 假设两者的数量分别为(a,b),不妨(a<b),在不考虑翻转的情况时,显然贪心进行拼接,即(10-01-cdots-10)
    • 显然,我们只需要对(lfloorfrac{b-a}{2} floor)(10)串进行翻转即可。
    • 最后选择翻转的策略是能翻转就翻转,我们用一个(map)来判断是否能翻转即可。
    • 另一种(ageq b)的情况类似。

    简而言之,贪心+(map)

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/14 19:48:43
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5;
     
    int n;
    string s[N];
    map <string, int> mp;
    int cnt[2][2];
    bool chk[N];
     
    string rev(string &S) {
        reverse(S.begin(), S.end());
        return S;
    }
     
    void run(){
        cin >> n;
        mp.clear();
        for(int i = 1; i <= n; i++) chk[i] = 0;
        cnt[0][1] = cnt[1][0] = 0;
        for(int i = 1; i <= n; i++) {
            cin >> s[i];
            int len = s[i].length();
            if(len > 1) {
                if(s[i][0] != s[i][len - 1]) mp[s[i]] = i;
                if(s[i][0] == '0' && s[i][len - 1] == '1') ++cnt[0][1];
                else if(s[i][0] == '1' && s[i][len - 1] == '0')++cnt[1][0];
            }    
        }
        if(cnt[0][1] == 0 && cnt[1][0] == 0) {
            int cnt1 = 0, cnt2 = 0;
            for(int i = 1; i <= n; i++) {
                int len = s[i].length();
                if(s[i][0] == '0' && s[i][len - 1] == '0') ++cnt1;
                else ++cnt2;   
            }
            if(cnt1 && cnt2) cout << -1 << '
    ';
            else cout << 0 << '
    ' << '
    ';
            return;   
        }
        int d = abs(cnt[0][1] - cnt[1][0]);
        int need = d / 2, ans;
        if(cnt[0][1] > cnt[1][0]) {
            for(int i = 1; i <= n && need; i++) {
                int len = s[i].length();
                if(len > 1 && s[i][0] == '0' && s[i][len - 1] == '1') {
                    rev(s[i]);
                    if(mp.find(s[i]) == mp.end()) {
                        --need; chk[i] = 1;  
                    } 
                    rev(s[i]);
                }   
            }
        } else {
            for(int i = 1; i <= n && need; i++) {
                int len = s[i].length();
                if(len > 1 && s[i][0] == '1' && s[i][len - 1] == '0') {
                    rev(s[i]);
                    if(mp.find(s[i]) == mp.end()) {
                        --need; chk[i] = 1;  
                    } 
                    rev(s[i]);
                }   
            }  
        }
        if(need == 0) ans = d / 2;   
        else {
            cout << -1 << '
    ';
            return;   
        }
        cout << ans << '
    ';
        for(int i = 1; i <= n; i++) if(chk[i]) cout << i << ' ';
        cout << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    

    E. Two Fairs

    题意:
    给出(n)个点,(m)条边的无向连通图。
    再给定两个点(a,b),询问((x,y))的对数。其中((x,y))为合法的一对需要满足(x)(y)的路径必须经过(a,b)这两个点。
    ((x,y),(y,x))为同一种情况。

    思路:
    一开始想的是将无向图缩点成一颗树,然后在树上搞。方法是可行的,但过于复杂。
    原问题为两点路径必须经过(a,b),也就是说,从(a)点出发,必须经过(b)才能到达某个点;从(b)出发。必须经过(a)才能到达某个点。
    那么我们跑两次(dfs),分别从(a,b)出发,找到从(a,b)出发不经过对方能到达的所有点,那么剩下的点就是必须经过才能到达的点。
    将两者的数量相乘即为答案。
    思路的本质是将“路径缩短”,原先跑(n)次的问题只需要跑两次。
    代码如下:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2019/12/14 20:12:26
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #define MP make_pair
    #define fi first
    #define se second
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << '
    '; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    void pt() {std::cout << '
    '; }
    template<typename T, typename...Args>
    void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 2e5 + 5, M = 5e5 + 5;
     
    int n, m, a, b;
    struct Edge {
        int v, next;
    }e[M << 1];
    int head[N], tot;
    void adde(int u, int v) {
        e[tot].v = v; e[tot].next = head[u]; head[u] = tot++;
    }
    int cnt;
    int col[N];
    void init() {
        for(int i = 1; i <= n; i++) head[i] = -1; tot = 0;   
    }
    void dfs(int u, int fa, int x) {
        col[u] = 1;
        if(u == x) return;   
        for(int i = head[u]; i != -1; i = e[i].next) {
            int v = e[i].v;
            if(!col[v]) dfs(v, u, x);
        }
    }
     
    void run(){
        cin >> n >> m >> a >> b;
        init();
        for(int i = 1; i <= m; i++) {
            int u, v; cin >> u >> v;
            adde(u, v); adde(v, u);
        }
        dfs(a, 0, b);
        int cnt1 = 0, cnt2 = 0;
        for(int i = 1; i <= n; i++) {
            cnt1 += 1 - col[i];
            col[i] = 0;   
        }
        dfs(b, 0, a);
        for(int i = 1; i <= n; i++) {
            cnt2 += 1 - col[i];   
            col[i] = 0;
        }
        ll ans = 1ll * cnt1 * cnt2;
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        int T; cin >> T;
        while(T--) run();
        return 0;
    }
    
  • 相关阅读:
    自定义动画animate()
    【Java】正则表达式
    【Java】连接数据库SQLServer
    【Java】导入导出TXT文件
    【数据库】SELECT语句
    数据结构与算法系列之目录
    【Java】员工统计
    【Java】生产者消费者模式
    【Java】购物超市
    【Java】导入导出Excel表格
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/12043602.html
Copyright © 2011-2022 走看看