Codeforces Round #648 (Div. 2)

传送门
视频题解

A. Matrix Game

简单博弈(贪心?)。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/7 22:39:24
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#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 << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    int n, m; cin >> n >> m;
    vector <vector <int>> a(n, vector <int>(m));
    vector <int> cols(m), rows(n);
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            cin >> a[i][j];
            if (a[i][j]) {
                ++cols[j];
                ++rows[i];
            }
        }
    }
    int cntr = 0, cntl = 0;
    for (int i = 0; i < n; i++) {
        if (rows[i] == 0) ++cntr;
    }
    for (int i = 0; i < m; i++) {
        if (cols[i] == 0) ++cntl;
    }
    int t = min(cntr, cntl);
    if (t & 1) {
        cout << "Ashish" << '
';
    } else {
        cout << "Vivek" << '
';
    }
}
 
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. Trouble Sort

注意到(b)中至少有一个(0),一个(1)必然可以任意排序;否则直接判断一下即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/7 22:44:07
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#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 << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    int n; cin >> n;
    vector <int> a(n), b(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        cin >> b[i];
    }
    sort(all(b));
    for (int i = 1; i < n; i++) {
        if (b[i] != b[i - 1]) {
            cout << "Yes" << '
';
            return;
        }
    }
    for (int i = 1; i < n; i++) {
        if (a[i] < a[i - 1]) {
            cout << "No" << '
';
            return;
        }
    }
    cout << "Yes" << '
';
}
 
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. Rotation Matching

求位置差值出现次数最多个数即可。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/7 23:22:04
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#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 << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    int n; cin >> n;
    vector <int> a(n), b(n);
    vector <vector <int>> v(n + 1); 
    for (int i = 0; i < n; i++) {
        cin >> a[i];
        v[a[i]].push_back(i);
        v[a[i]].push_back(i + n);
    }
    vector <int> cnt(n);
    for (int i = 0; i < n; i++) {
        cin >> b[i];
        for (auto it : v[b[i]]) {
            if (it >= i && it - i < n) {
                ++cnt[it - i];
            }
        }
    }
    int ans = *max_element(all(cnt));
    cout << ans << '
';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

D. Solve The Maze

贪心堵住坏人,然后从终点出发bfs即可。
细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/7 23:29:38
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#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 << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    int n, m; cin >> n >> m;
    vector <string> mz(n);
    int cnt = 0;
    for (int i = 0; i < n; i++) {
        cin >> mz[i];
        for (int j = 0; j < m; j++) {
            if (mz[i][j] == 'G') ++cnt;
        }
    }
    if (cnt == 0) {
        cout << "Yes" << '
';
        return;
    }
    const int dx[] = {-1, 1, 0, 0}, dy[] = {0, 0, -1, 1};
    auto ok = [&] (int x, int y) {
        return x >= 0 && x < n && y >= 0 && y < m;
    };
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (mz[i][j] == 'B') {
                for (int k = 0; k < 4; k++) {
                    int x = i + dx[k], y = j + dy[k];
                    if (ok(x, y)) {
                        if (mz[x][y] == '#') {}
                        if (mz[x][y] == '.') mz[x][y] = '#';
                        if (mz[x][y] == 'B') {}
                        if (mz[x][y] == 'G') {
                            cout << "No" << '
';
                            return;
                        }
                    }
                }
            }
        }
    }
    if (mz[n - 1][m - 1] == '#') {
        cout << "No" << '
';
        return;
    }
    vector <vector <int>> d(n, vector <int>(m, -1));
    queue <pii> q;
    q.push(MP(n - 1, m - 1));
    d[n - 1][m - 1] = 0;
    while (!q.empty()) {
        pii now = q.front(); q.pop();
        int x = now.fi, y = now.se;
        for (int k = 0; k < 4; k++) {
            int nx = x + dx[k], ny = y + dy[k];
            if (ok(nx, ny) && mz[nx][ny] != '#') {
                if (d[nx][ny] == -1) {
                    d[nx][ny] = d[x][y] + 1;
                    q.push(MP(nx, ny));   
                }
            }   
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < m; j++) {
            if (mz[i][j] == 'B' && d[i][j] != -1) {
                cout << "No" << '
';
                return;   
            }
            if (mz[i][j] == 'G' && d[i][j] == -1) {
                cout << "No" << '
';
                return;
            }
        }
    }
    cout << "Yes" << '
';
}
 
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. Maximum Subsequence Value

注意到(k>3)的时候解一定没有前面优,大概的证明可以看看视频,如果有更优的那么之前的也能最优。
所以只用考虑(kleq 3)的情况,所以(O(n^3))枚举就行。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/7 23:56:36
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#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 << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    int n; cin >> n;
    vector <ll> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    if (n == 1) {
        cout << a[0] << '
';
        return;
    }
    ll ans = *max_element(all(a));
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            ans = max(ans, (a[i] | a[j]));
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            for (int k = j + 1; k < n; k++) {
                ans = max(ans, (a[i] | a[j]) | a[k]);
            }
        }
    }
    cout << ans << '
';
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}

F. Swaps Again

注意到对称位置上的数经过若干次操作过后位置也是对称的。
所以直接(O(n^2))模拟就行。

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/8 0:58:57
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#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 << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1e5 + 5;
 
void run() {
    int n; cin >> n;
    vector <int> a(n), b(n), c(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    for (int i = 0; i < n; i++) {
        cin >> b[i];
    }
    vector <bool> vis(n);
    for (int i = 0; i < n / 2; i++) {
        int j = n - i - 1;
        for (int k = 0; k < n; k++) {
            if (!vis[k]) {
                if (a[i] == b[k] && a[j] == b[n - k - 1]) {
                    c[k] = a[i];
                    c[n - k - 1] = a[j];
                    vis[k] = vis[n - k - 1] = true;
                    break;
                }
            }
        }
    }
    if (n & 1) {
        c[n / 2] = a[n / 2];
    }
    for (int i = 0; i < n; i++) {
        if (c[i] != b[i]) {
            cout << "No" << '
';
            return;
        }
    }
    cout << "Yes" << '
';
}
 
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;
}

G. Secure Password

(val[i][0/1])表示当下标中第(i)个二进制位为(0/1),其余任意时,所有数或起来的值。
那么对于每个下标可以每个二进制位单独计算,最后总的值或起来即是答案。
但这种思路我们会询问(2logn)次,显然会超过(13),考虑只用(val[i][0])或者(val[i][1])来进行表示,这样询问次数满足条件,但是不能处理下标之间包含的关系,比如((i& j=i))这种。
考虑将每个下标进行映射,映射过后任意两个下标都不存在包含与被包含的关系并且互不相等,此时可以只用(val[i][0])或者(val[i][1])得到答案。
我们可以将每个数映射为包含(6)(1)的二进制数,({13choose 6}=1716>1000),所以这样肯定能够映射完所有的数的,之后直接对每个下标求解答案即可。
询问次数至少为(logn)次。
映射的这步十分巧妙!!其实前面的思路还比较好想,关键就是后面这里,神仙。。
细节见代码:

Code
/*
 * Author:  heyuhhh
 * Created Time:  2020/6/8 19:27:10
 */
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
#include <queue>
#include <iomanip>
#include <assert.h>
#include <functional>
#include <numeric>
#define MP make_pair
#define fi first
#define se second
#define pb push_back
#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 << std::endl; }
  template<typename T, typename...Args>
  void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  template <template<typename...> class T, typename t, typename... A> 
  void err(const T <t> &arg, const A&... args) {
  for (auto &v : arg) std::cout << v << ' '; err(args...); }
#else
  #define dbg(...)
#endif
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
//head
const int N = 1000 + 5, P = 13;
 
void run() {
    int n;
    cin >> n;
    vector <vector <int>> bit(P);
    vector <int> change(n);
    int k = 0;
    for (int i = 0; i < 1 << P; i++) {
        if (__builtin_popcount(i) != P / 2) continue;
        for (int j = 0; j < P; j++) {
            if (!(i >> j & 1)) {
                bit[j].push_back(k + 1);
            }
        }   
        change[k++] = i;
        if (k == n) break;
    }
    auto query = [&] (vector <int>& q) {
        cout << '?' << ' ' << sz(q);
        for (auto it : q) {
            cout << ' ' << it;
        }
        cout << '
' << endl;
        ll t; cin >> t;
        return t;
    };
    vector <ll> val(P);
    for (int i = 0; i < P; i++) {
        if (sz(bit[i])) {
            val[i] = query(bit[i]);
        }
    }
    vector <ll> A(n);
    for (int i = 0; i < n; i++) {
        int x = change[i];
        for (int j = 0; j < P; j++) {
            if (x >> j & 1) {
                A[i] |= val[j];
            }
        }
    }
    cout << "!";
    for (int i = 0; i < n; i++) {
        cout << ' ' << A[i];
    }
    cout << endl;
}
 
int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    cout << fixed << setprecision(20);
    run();
    return 0;
}
原文地址:https://www.cnblogs.com/heyuhhh/p/13064328.html