2023.6.20 每日一题

原题链接

A: Educational Codeforces Round 115 (Rated for Div. 2) - E

B: Codeforces Round 698 (Div. 2) - C

A. Staircases - 2100

题目大意

给定一个 \(n\times m\) 的网格,每个格子为自由或者锁定,初始时所有格子均为自由的。

定义满足如下条件的路径为楼梯:

  • 起点和终点均为自由的

  • 路径上的所有点均为自由的

  • 满足以下两种结构之一

    1.第二个格子在第一个格子右面,第三个格子在第二个格子下面,第四个格子在第三个格子右面,以此类推……

    2.第二个格子在第一个格子下面,第三个格子在第二个格子右面,第四个格子在第三个格子下面,以此类推……

此外,一个单独的自由格子也被视为一个楼梯。

给定 \(q\) 个询问,每个询问给定整数 \(x、y\),并将格子 \((x,y)\) 颜色翻转。

输出每次操作后网格中不同楼梯的个数。

解题思路

首先我们肯定知道求不同的楼梯个数是通过一个二维的dp来解决。可以使用额外的一维来存储是否被锁定的数据。

因为我们只能向右向下走,那么很明显dp的转移就是左格子和上格子加一。当然因为单独一个自由格也算是一个楼梯,那么我们需要去重处理一下。

最后递归处理修改后的情况即可。

注:这里并不是dfs,只是递归习惯性命名dfs。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 1e3 + 10;
const int MOD = 1e9 + 7;

int n, m, q;
LL dp[N][N][2];
LL res;
bool vis[N][N];

void dfs(int x, int y, int op) {
    if (x > n || x < 0 || y > m || y < 0) return;
    res -= dp[x][y][op];
    dp[x][y][op] = 0;
    if (!vis[x][y]) {
        dp[x][y][op] = dp[x - !op][y - op][!op] + 1;
    }
    res += dp[x][y][op];
    dfs(x + op, y + !op, !op);
}

void solve() {
    cin >> n >> m >> q;
    for (int i = 1; i <= n; ++i) {
        for (int j = 1; j <= m; ++j) {
            dp[i][j][0] += dp[i - 1][j][1] + 1;
            dp[i][j][1] += dp[i][j - 1][0] + 1;
            res += dp[i][j][0] + dp[i][j][1];
        }
    }
    res -= n * m;
    while (q--) {
        int x, y;
        cin >> x >> y;
        vis[x][y] = !vis[x][y];
        vis[x][y] ? res++ : res--;
        dfs(x, y, 0);
        dfs(x, y, 1);
        cout << res << endl;
    }
}

signed main() {
    ios;
    int T = 1;
//    cin >> T;
    while (T--) {
        solve();
    }
}

B.Nezzar and Symmetric Array - 1700

题目大意

定义长度为 \(2 \times n\) 的数组 \(a\)\(a\) 中的元素不重复,并且对于任意一个下标\(i(1 \leq i \leq 2 \cdot n, i \ne j)\),都能找到一个下标 \(j\),使得 \(a_i = -a_j\)

现在给定一个数组 \(d\),其中 \(d_i = \sum_{j=1}^{2n}|a_i -a_j|\),问能不能通过数组 \(d\) 构造出数组 \(a\)

解题思路

其实就是数学贪心推式子嘛,看了看觉得洛谷的题解很不错,就不再分析了,直接把代码贴在下面。

AC Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#include <map>
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;
typedef long long LL;

const int N = 2e5 + 10;
const int MOD = 1e9 + 7;

LL a[N], s[N];

void solve() {
    int n;
    cin >> n;
    for (int i = 1; i <= (n << 1); ++i) {
        cin >> a[i];
    }
    sort(a + 1, a + (n << 1) + 1);
    for (int i = 1; i <= n; ++i) {
        if (a[i << 1] != a[(i << 1) - 1]) {
            cout << "NO" << endl;
            return;
        }
    }
    LL cnt = unique(a + 1, a + (n << 1) + 1) - (a + 1);
    if (cnt != n) {
        cout << "NO" << endl;
        return;
    }
    for (int i = 2; i <= n; ++i) {
        s[i] = s[i - 1] + (a[i] - a[i - 1]) / ((i - 1) << 1);
        if ((a[i] - a[i - 1]) % ((i - 1) << 1) || (a[i] - a[i - 1]) <= 0) {
            cout << "NO" << endl;
            return;
        }
    }
    for (int i = 1; i <= n; ++i) {
        a[1] -= s[i] << 1;
    }
    cout << (a[1] % (n << 1) || a[1] <= 0 ? "NO" : "YES") << endl;
}

signed main() {
    ios;
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
}
posted @ 2023-06-20 17:21  叁纔  阅读(18)  评论(0编辑  收藏  举报