2023河南萌新联赛第(五)场:郑州轻工业大学

2023河南萌新联赛第(五)场:郑州轻工业大学

D 01分数规划

给你一个字符串 s s s,由 0 0 0 1 1 1 ? ? ?组成, ? ? ?可以替换为 1 1 1 0 0 0,求可能的最长的 1 1 1串或 0 0 0串的长度。

可以用 d p dp dp直接把 ? ? ?的可能状态进行转移

也可以直接把所有 ? ? ?看成 1 1 1跑一遍,再看成 0 0 0跑一边取最大。

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    int n;
    cin >> n;
    string s;
    cin >> s;
    vector<vector<int>> dp(2, vector<int>(2));
    int ans = 0;
    for (int i = 0; i < n; i++) {
        if (s[i] == '?') {
            dp[i & 1][0] = dp[(i + 1) & 1][0] + 1;
            dp[i & 1][1] = dp[(i + 1) & 1][1] + 1;
        } else if (s[i] == '1') {
            dp[i & 1][1] = dp[(i + 1) & 1][1] + 1;
            dp[i & 1][0] = 0;
        } else {
            dp[i & 1][0] = dp[(i + 1) & 1][0] + 1;
            dp[i & 1][1] = 0;
        }
        ans = max(dp[i & 1][0], ans);
        ans = max(dp[i & 1][1], ans);
    }
    cout << ans << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

B 亚托莉 -我挚爱的时光-

模拟安装,卸载(不清除个人数据,清除个人数据),以及删库跑路

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    set<string> soft, data;
    int n;
    cin >> n;
    while (n--) {
        string s;
        cin >> s;
        if (s == "1") {
            cin >> s;
            if (soft.count(s)) {
                cout << "yes" << endl;
            } else {
                cout << "no" << endl;
            }
        } else if (s == "2") {
            cin >> s;
            if (data.count(s)) {
                cout << "yes" << endl;
            } else {
                cout << "no" << endl;
            }
        } else if (s == "pacman") {
            cin >> s;
            if (s == "-R") {
                cin >> s;
                soft.erase(s);
            } else {
                cin >> s;
                soft.erase(s);
                data.erase(s);
            }
        } else {
            cin >> s;
            if (s == "pacman") {
                cin >> s >> s;
                soft.insert(s);
                data.insert(s);
            } else {
                cout << "wuwuwu" << endl;
                exit(0);
            }
        }
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
//     cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

J 树上DP

节点的深度越大在子树中出现的次数越多

计算每个点的深度,再将其和 a i a_i ai排序求乘积和就是最大

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    int n;
    cin >> n;
    vector<vector<int>> g(n);
    vector<int> a(n), dep(n), val(n, 1);
    for (int i = 1; i < n; i++) {
        int x, y;
        cin >> x >> y;
        x--, y--;
        g[x].push_back(y);
        g[y].push_back(x);
    }
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    auto dfs = [&](auto self, int x, int fa) -> void {
        for (auto u : g[x]) {
            if (u == fa) continue;
            dep[u] = dep[x] + 1;
            self(self, u, x);
        }
        };
    dep[0] = 1;
    dfs(dfs, 0, -1);
    sort(a.begin(), a.end());
    sort(dep.begin(), dep.end());
    int ans = 0;
    for (int i = 0; i < n; i++) {
        ans += a[i] * dep[i];
    }
    cout << ans << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

G Kruskal

可以发现,除了 n n n每位都是 1 1 1的时候答案为 1 1 1之外,其他答案都是 0 0 0

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    int n;
    cin >> n;
    while (n) {
        if (n & 1) {
            n >>= 1;
        } else {
            cout << 0 << endl;
            return;
        }
    }
    cout << 1 << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

I 双指针

等式两边转化一下,变成 a i b i = b j a j \frac{a_i}{b_i} = \frac{b_j}{a_j} biai=ajbj

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    int n;
    cin >> n;
    vector<int> a(n), b(n);
    for (auto& x : a) cin >> x;
    for (auto& x : b) cin >> x;
    map<double, int> mp;
    int ans = 0;
    for (int i = 0; i < n; i++) {
        ans += mp[b[i] * 1.0 / a[i]];
        mp[a[i] * 1.0 / b[i]]++;
        // cout << i << ' ' << ans << endl;
    }
    cout << ans << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

A 买爱心气球

找规律可以发现 m m o d    3 = = n m \mod 3==n mmod3==n时后手才能赢

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    int m, n;
    cin >> m >> n;
    if (n == m % 3) {
        cout << "Bob" << endl;
    } else {
        cout << "Alice" << endl;
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

E 换根DP

其实就是考虑哪条 1 1 1边将树分的最不平均,取重的一边都是 1 1 1,轻的一边都是 2 2 2

这样我们只需从所有叶子开始向内即可,对边为1的特殊处理一下

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    int n;
    cin >> n;
    vector<vector<pii>> g(n);
    vector<int> du(n), sz(n, 1);
    for (int i = 1; i < n; i++) {
        int x, y, w;
        cin >> x >> y >> w;
        x--, y--;
        g[x].push_back({ y, w });
        g[y].push_back({ x, w });
        du[x]++;
        du[y]++;
    }
    queue<int> q;
    for (int i = 0; i < n; i++) {
        if (g[i].size() == 1) {
            q.push(i);
        }
    }
    int ans = n - 1;
    while (q.size()) {
        auto x = q.front();
        // cout << x << ' ' << sz[x] << endl;
        q.pop();
        for (auto [u, v] : g[x]) {
            if (v == 1) {
                ans = min(ans, sz[x]);
            }
            du[u]--;
            if (du[u] == 1) {
                sz[u] += sz[x];
                q.push(u);
            } else {
                sz[u] += sz[x];
            }
        }
    }
    cout << n - 2 + ans << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    // cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

L 异或与

可以发现,两个数要满足条件就需要从低位开始看,只有碰到都是 1 1 1的时候下一位才是不一样的,其他都是 0 0 0

#include <bits/stdc++.h>
typedef long long ll;
#define int ll
#define endl '\n'
#define lowbit(x) (x & (-x))
#define pii pair<int, int>
#define debug(x) cout << #x << " = " << x << endl
using namespace std;

const int INF = 0x3f3f3f3f3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-9;
const int mod = 998244353;
const int N = 2e5 + 10;

void solve() {
    int n;
    cin >> n;
    map<int, int> mp;
    auto calc = [&] (int x) {
        int res = 0;
        for (int i = 0; i < 61; i++) {
            if (x >> i & 1) {
                res |= (1ll << i);
                if (!(x >> (i + 1) & 1)) {
                    res |= (1ll << (i + 1));
                }
                i++;
            }
        }
        return res;
    };
    for (int i = 1, x; i <= n; i++) {
        cin >> x;
        if (mp[x]) {
            cout << mp[x] << ' ' << i << endl;
            return;
        }
        mp[calc(x)] = i;
    }
    cout << -1 << endl;
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr), cout.tie(nullptr);
    int T = 1;
    // cin >> T;
    while (T--) {
        solve();
    }
    return 0;
}

M 扫描线

旋转卡壳

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值