...

牛客小白月赛106

牛客小白月赛106

比赛链接:牛客小白月赛106
//也就写写水题骗自己了

A.最后DISCO

直接秒,注意一下c可以等于0

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    if (b == 0)a = 1;
    int tmp = (a * c) % 2 + d;
    if (tmp & 1)
        cout << "YES\n";
    else cout << "NO\n";
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

B.末日DISCO

构造矩阵为

++sum ++sum ++sum ++sum ……

++sum arr[i1][i] ++sum ++sum ……

++sum arr[i2][i] arr[i1][i] ++sum ……

​ …… …… …… ……

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int n;
    cin >> n;
    int sum = n;
    vector<vector<int>> ans(n + 1, vector<int>(n + 1));
    for (int i = 1; i <= n; i++)ans[1][i] = i;
    for (int i = 2; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (j >= 2 && j <= i)
                ans[i][j] = ans[j - 1][i];
            else
                ans[i][j] = ++sum;
        }
    }

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)cout << ans[i][j] << " \n"[j == n];
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

C.明日DISCO

​ 让棋盘上所有数相等,已知0n+1都为0,且观察两种操作发现无法改变棋盘边缘值,所以使最终棋盘上所有数相等只能使得所有点为0

​ 那么用队列装入所有可以进行操作的格子,进行bfs即可,注意到每次修改之后可能会让其上下左右的格子变得可以操作,bfs跑完之后去暴力判断棋盘上是否全为0即可

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int n;
    cin >> n;
    int sum = n;
    vector<vector<int>> arr(n + 2, vector<int>(n + 2));
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)cin >> arr[i][j];

    queue<PII > q;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (arr[i][j] > max({arr[i - 1][j], arr[i][j - 1], arr[i + 1][j], arr[i][j + 1]}))
                q.push(make_pair(i, j));
        }
    }

    while (q.size()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        arr[x][y] = max({arr[x - 1][y], arr[x + 1][y], arr[x][y - 1], arr[x][y + 1]});
    }

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (arr[i][j] < min({arr[i - 1][j], arr[i][j - 1], arr[i + 1][j], arr[i][j + 1]}))
                q.push(make_pair(i, j));
        }
    }

    while (q.size()) {
        int x = q.front().first;
        int y = q.front().second;
        q.pop();
        arr[x][y] = min({arr[x - 1][y], arr[x + 1][y], arr[x][y - 1], arr[x][y + 1]});
    }

    bool ok = false;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
            if (arr[i][j])ok = true;
    if (ok)cout << "NO\n";
    else cout << "YES\n";
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

D.太阳系DISCO

​ 仔细观察题目发现发动技能最多进行一次,大于一次的使用技能是没有意义的,那么可以视作两个起点往终点走,那么直接bfsdij即可

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int n, k, a, b, x, y;
    cin >> n >> k >> a >> b >> x >> y;
    vector<bool> st(n + 1);
    priority_queue<PII, vector<PII >, greater<PII>> q;
    q.push(make_pair(0, a));
    if (k) {
        int pos = a + n / 2;
        if (pos > n)pos = pos % n;
        q.push(make_pair(1, pos));
        st[pos] = true;
    }
    st[a] = true;
    int ans = inf;
    while (q.size()) {
        auto tmp = q.top();
        q.pop();
        if (tmp.second == b) {
            ans = min(ans, tmp.first);
            break;
        }
        int pos = tmp.second + x;
        if (pos > n)pos = pos % n;
        if (!st[pos]) {
            st[pos] = true;
            q.push(make_pair(tmp.first + 1, pos));
        }
        pos = tmp.second - y;
        if (pos <= 0)pos += n;
        if (!st[pos]) {
            st[pos] = true;
            q.push(make_pair(tmp.first + 1, pos));
        }
    }
    if (ans == inf)cout << -1 << endl;
    else cout << ans << endl;
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

E.普通DISCO-1

​ 小丑题。拿一根从根节点出发的最长链,再链接上与其不相交的最长链相连即可,然后特判为一条链的情况就好了。

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT32_MAX
#define PII pair<int,int>
#define endl '\n'

inline void solve() {
    int n;
    cin >> n;
    vector<vector<int>> arr(n + 1);
    for (int i = 1, x, y; i < n; i++) {
        cin >> x >> y;
        arr[x].push_back(y);
        arr[y].push_back(x);
    }
    vector<int> res;
    vector<int> len(n + 1);
    function<void(int, int)> dfs = [&](int x, int fa) {
        for (int y: arr[x]) {
            if (y == fa)continue;
            dfs(y, x);
            len[x] = max(len[x], len[y] + 1);
        }
        bool ok = false;
        for (int y: arr[x]) {
            if (y == fa)continue;
            if (len[y] + 1 == len[x] && !ok) {
                ok = true;
                continue;
            }
            res.push_back(len[y] + 1);
        }
    };

    dfs(1, 0);
    res.push_back(len[1]);
    sort(res.begin(), res.end(), greater<int>());
    if (res.size() == 1) {
        cout << res.front() + 1 << endl;
        return;
    }
    cout << res[0] + res[1] << endl;
}


signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}

E.普通DISCO-2

​ 从贪心的角度去思考,一定是拿最长链所在点与其不为祖先节点的点相连最优,那么如果有多条最长链,那么把这些最长链全部移到其非祖先节点的节点上的过程其实等价于将这条链形成的子树移过去,那么此时树中最长链一定由这两个点产生。

​ 至此做法已经呼之欲出了,使用二分,把所有深度大于mid的节点求出其公共祖先,然后依次那与其不成祖先关系的节点进行操作,然后看答案是否满足小于等于mid

#include <bits/stdc++.h>

using namespace std;
#define int long long
#define inf INT64_MAX
#define PII pair<int,int>
#define endl '\n'
#define double long double
const int N = 5e5 + 7;
int deep[N], f[N], son[N], sz[N], top[N];//用于求LCA
int len[N];//记录当前点向下形成的最长链
vector<vector<int>> arr(N);

void dfs1(int x, int father) {
    deep[x] = deep[father] + 1;
    f[x] = father;
    sz[x] = 1;
    for (int y: arr[x]) {
        if (y != father) {
            f[y] = x;
            dfs1(y, x);
            sz[x] += sz[y];
            if (!son[x] || sz[son[x]] < sz[y])son[x] = y;
        }
    }
}

void dfs2(int x, int topx) {
    top[x] = topx;
    if (!son[x])return;
    dfs2(son[x], topx);
    for (int y: arr[x]) {
        if (y != f[x] && y != son[x]) {
            dfs2(y, y);
        }
    }
}

inline int LCA(int x, int y) {
    while (top[x] != top[y]) {
        if (deep[top[x]] < deep[top[y]])swap(x, y);
        x = f[top[x]];
    }
    return deep[x] < deep[y] ? x : y;
}

void solve() {
    int n;
    cin >> n;
    for (int i = 1; i < n; i++) {
        int x, y;
        cin >> x >> y;
        arr[x].push_back(y);
        arr[y].push_back(x);
    }

    deep[1] = 1;
    dfs1(1, 0);
    dfs2(1, 0);
    auto init = [&](auto self, int x, int fa) -> void {
        len[x] = 1;
        for (int y: arr[x]) {
            if (y == fa)continue;
            self(self, y, x);
            len[x] = max(len[x], len[y] + 1);
        }
    };
    init(init, 1, 0);

    int l = 1, r = *max_element(deep + 1, deep + n + 1);
    int ans = r;
    auto check = [&](int x) {
        int head = -1;
        for (int i = 1; i <= n; i++)
            if (deep[i] > x) {//实际上是对其父节点进行操作,也就是置换两个节点的儿子
                if (head == -1)head = f[i];
                else head = LCA(head, f[i]);
                if (head == 1)return false;//如果lca等于根节点那么就无法操作了
            }


        for (int i = 1; i <= n; i++) {
            int tmp = LCA(i, head);
            if (tmp == i || tmp == head)continue;
            if (deep[head] + len[i] - 1 <= x && deep[i] - 1 + len[head] <= x)return true;
        }
        return false;
    };
    while (l + 1 < r) {
        int mid = (l + r) >> 1;
        if (check(mid))r = mid;
        else l = mid;

    }
    cout << r << endl;
}

signed main() {
#ifdef ONLINE_JUDGE
#else
    freopen("test.in", "r", stdin);
    freopen("test.out", "w", stdout);
#endif
    ios::sync_with_stdio(0);
    cout.tie(0);
    cin.tie(0);
    int t = 1;
//    cin >> t;
    while (t--)
        solve();
    return 0;
}
posted @   让你飞起来  阅读(2)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示