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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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 << '\n';
}
 
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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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 << '\n';
}
 
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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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 << '\n';
    for(int i = 1; i <= n; i++) if(del[i]) cout << i << ' ';
    cout << '\n';
}
 
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\)
  • 显然,我们只需要对\(\lfloor\frac{b-a}{2}\rfloor\)\(10\)串进行翻转即可。
  • 最后选择翻转的策略是能翻转就翻转,我们用一个\(map\)来判断是否能翻转即可。
  • 另一种\(a\geq 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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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 << '\n';
        else cout << 0 << '\n' << '\n';
        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 << '\n';
        return;   
    }
    cout << ans << '\n';
    for(int i = 1; i <= n; i++) if(chk[i]) cout << i << ' ';
    cout << '\n';
}
 
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 << '\n'; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
#else
  #define dbg(...)
#endif
void pt() {std::cout << '\n'; }
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 << '\n';
}
 
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;
}
posted @ 2019-12-15 11:33  heyuhhh  阅读(284)  评论(0编辑  收藏  举报