日常刷题2025-1-25

日常刷题2025-1-25

绝妙的平衡

rating:1400

https://ac.nowcoder.com/acm/contest/67746/J

思路(树形DP+小巧思)

首先考虑什么情况下会无解?显然是一个父亲和他的所有儿子都是红色节点的时候,此时该节点只能赋值为0,因此无解。 只要没这种情况,我们就可以默认的将所有白色节点赋值为2,然后一旦遇到某红色节点不得不用0的时候,我们将该红色节点和它的任意一个白色儿子同时变成1即可。

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const long long LINF = 1e18;

void solve(){
    int n;
    std::string s;
    std::cin >> n >> s;

    s = ' ' + s;

    std::vector<int> fa(n+1), ans(n+1, 1);
    std::vector g(n+1, std::vector<int>());
    std::vector<int> dp(n+1, 1);

    for (int i = 1; i <= n - 1; i++){
        std::cin >> fa[i+1];
        g[fa[i+1]].push_back(i+1);
    }

    auto dfs = [&](auto self, int cur) ->void{
        int red = 0;
        for (auto to : g[cur]){
            self(self, to);
            if (s[to] == 'R') {
                red++;
            }else{
                dp[cur] += dp[to];
            }
        }

        if (red == g[cur].size() && s[cur] == 'R'){
            std::cout << "-1\n";
            exit(0);
        }
        if (s[cur] == 'R'){
            if (dp[cur] % 3 == 0){
                ;
            }else if (dp[cur] % 3 == 1){
                ans[cur] = 2;
                for (auto to : g[cur]){
                    if (s[to] != 'R'){
                        ans[to] = 2;
                        break;
                    }
                }
                
            }else if (dp[cur] % 3 == 2){
                ans[cur] = 2;
            }
        }
    };

    dfs(dfs, 1);

    for (int i = 1; i <= n; i++){
        std::cout << ans[i];
    }
    std::cout << '\n';


}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}

C. Remove Exactly Two

https://codeforces.com/contest/2063/problem/C

思路(图论)

https://www.bilibili.com/video/BV1C5fWYoEat/?spm_id_from=333.1007.tianma.1-3-3.click&vd_source=4a339d299e165d8fe38b9926c5240eae

评述

思考问题非常不全面,太想当然了。没有深刻理解问题。

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const long long LINF = 1e18;

void solve(){
    int n;
    std::cin >> n;

    std::vector<int> deg(n+1, 0);
    std::vector g(n+1, std::vector<int>());
    for (int i = 0; i < n - 1; i++){
        int u, v;
        std::cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
        deg[u]++, deg[v]++;
    }

    std::multiset<int> st;
    for (int i = 1; i <= n; i++) st.insert(deg[i]);
    int res = 0;
    auto dfs = [&](auto self, int cur, int fa)->void{
        if (fa != -1){
            res = std::max(res, deg[cur] + deg[fa] - 2);
        }
        for (auto to : g[cur]){
            if (to == fa) continue;
            self(self, to, cur);
        }
        
        st.erase(st.find(deg[cur]));
        for (auto to : g[cur]){
            st.erase(st.find(deg[to]));
        }
        if (!st.empty()){
            res = std::max(res, deg[cur] - 1 + *st.rbegin());
        }
        st.insert(deg[cur]);
        for (auto to : g[cur]){
            st.insert(deg[to]);
        }
    };

    dfs(dfs, 1, -1);

    std::cout << res << '\n';
}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    std::cin >> t; 
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}

D. Card Game

rating:1400

https://codeforces.com/problemset/problem/1932/D

思路(暴力模拟)

就是模拟

代码

#include <bits/stdc++.h>

using i64 = long long;

void solve() {
    int n;
    std::cin >> n;
    
    char tr;
    std::cin >> tr;
    
    std::map<char, std::vector<std::string>> f;
    for (int i = 0; i < 2 * n; i++) {
        std::string s;
        std::cin >> s;
        f[s[1]].push_back(s);
    }
    
    std::vector<std::array<std::string, 2>> ans;
    for (auto c : {'C', 'D', 'H', 'S'}) {
        std::sort(f[c].begin(), f[c].end());
        if (c == tr) {
            continue;
        }
        for (int i = 0; i + 1 < f[c].size(); i += 2) {
            ans.push_back({f[c][i], f[c][i + 1]});
        }
        if (f[c].size() % 2 == 1) {
            if (f[tr].empty()) {
                std::cout << "IMPOSSIBLE\n";
                return;
            }
            auto t = f[tr].back();
            f[tr].pop_back();
            ans.push_back({f[c].back(), t});
        }
    }
    
    for (int i = 0; i + 1 < f[tr].size(); i += 2) {
        ans.push_back({f[tr][i], f[tr][i + 1]});
    }
    
    for (auto [x, y] : ans) {
        std::cout << x << " " << y << "\n";
    }
}

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
    int t;
    std::cin >> t;
    
    while (t--) {
        solve();
    }
    
    return 0;
}

C. LR-remainders

rating:1400

https://codeforces.com/problemset/problem/1932/C

思路(小巧思)

题目的问题在于不知道数的顺序,如果知道的话,我们可以很轻易维护出上一个数除以 m 的余数是多少,然后直接用余数乘以下一个数,这样就不用怕越界的问题。但是我们知道每个数删除的顺序,所以我们能够根据它得到每个数处理的顺序。

代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int maxn = 2e6 + 5;


ll pre[maxn];

int num[maxn];
ll mod;
ll powmod(ll x, ll y) {
    if (y == 0) return 1;
    ll t = powmod(x, y / 2);
    if (t % 2 == 0) return t * t % mod;
    else return t * t % mod * x % mod;
}
ll a[maxn], res[maxn];
void solve() {

    int n;
    cin >> n;
    cin >> mod;
    ll ans = 1;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    string s;
    cin >> s;

    int l = 1, r = n;
    stack<int> sta;
    for (int i = 0; i < n; i++) {
        if (s[i] == 'L') {
            sta.push(l++);
        }
        else {
            sta.push(r--);
        }
    }
    ans = 1;
    for (int i = n; i >= 1; i--) {
        ll now = a[sta.top()];
        sta.pop();
        ans = ans * now % mod;
        res[i] = ans;
    }

    for (int i = 1; i <= n; i++) cout << res[i] << " ";
    cout << endl;
}

int main() {
    ios::sync_with_stdio(0);
    int T;
    cin >> T;
    while (T--) solve();
}

E. Anna and the Valentine's Day Gift

rating:1400

https://codeforces.com/problemset/problem/1931/E

思路(博弈)

首先是Anna最后想让数位尽量少,Sasha想让数位尽量多。Anna只能让后导零减少,交替操作中Sasha也能抢到一部分后导零。我们先假设所有数位都被Sasha抢到了,再减去Anna抢到的部分后导零即可。每次抢后导零时都会抢后导零最多的。

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const long long LINF = 1e18;

void solve(){
    int n, m;
    std::cin >> n >> m;

    int len = 0;
    std::vector<std::string> a(n);
    for (int i = 0; i < n; i++){
        std::cin >> a[i];
        len += a[i].size();
    }

    std::vector<int> ans;

    for (int i = 0; i < n; i++){
        int r = a[i].size() - 1;
        while (r >= 0 && a[i][r] == '0'){
            r--;
        }
        int cnt = a[i].size() - 1 - r;
        if (cnt == 0) continue;
        ans.push_back(cnt);
    }

    std::sort(ans.begin(), ans.end());

    int ll = ans.size();

    for (int i = ll - 1; i >= 0; i -= 2){
        len -= ans[i];
    }

    std::cout << (len <= m  ? "Anna" : "Sasha") << '\n';
}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    std::cin >> t; 
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}

P1064 [NOIP2006 提高组] 金明的预算方案

rating:普及+/提高

https://www.luogu.com.cn/problem/P1064

思路(分组背包)

比较板的分组背包,把每个主件看作一个组,由于附件比较少一个最多只有2个,所以可以暴力列举出所有可能,然后跑一个分组背包。

最后有一个样例没有过,原因是默认以为是先读入主件,附件会在后面过来,所以\(g[i][0]\)默认是主件,但是样例#11卡了这个点,来了个先出附件再出主件的样例。

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const long long LINF = 1e18;

void solve(){
    int n, m, cnt = 0;
    std::cin >> n >> m;

    std::vector<int> v(n+1), p(n+1);
    std::map<int, std::vector<int>> dic;

    for (int i = 1; i <= m; i++){
        int fa;
        std::cin >> v[i] >> p[i] >> fa;
        p[i] *= v[i];
        if (fa == 0) {
            dic[i].push_back(i);
            cnt++;
        }
        else {
            dic[fa].push_back(i);
        }
    }

    std::vector g(cnt + 2, std::vector<pii>());
    int idx = 1;
    for (auto [x, arr] : dic){
        g[idx].push_back({v[arr[0]], p[arr[0]]});
        int allv = 0, allp = 0;
        for (int i = 1; i < arr.size(); i++){
            g[idx].push_back({v[arr[0]]+v[arr[i]], p[arr[0]]+p[arr[i]]});
            allv += v[arr[i]], allp += p[arr[i]];
        }
        if (arr.size() == 3)
            g[idx].push_back({v[arr[0]]+allv, p[arr[0]]+allp});
        idx++;
    }

    /*
    f[i][j]:表示前i组物品在不超过j这个价格的情况下重要度和价值的乘积的最大值。
    */
    std::vector<int> f(n+1);
    for (int i = 1; i <= cnt; i++){
        for (int j = n; j >= 0; j--){
            for (int k = 0; k < g[i].size(); k++){
                if (j >= g[i][k].first){
                    f[j] = std::max(f[j], f[j-g[i][k].first] + g[i][k].second);
                }
            }
        }
    }

    // for (int i = 0; i <= cnt; i++){
    //     std::cout << f[i] << ' ';
    // }

    std::cout << f[n] << '\n';
}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}
posted @ 2025-01-25 10:44  califeee  阅读(25)  评论(0)    收藏  举报