日常刷题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;
}

本文作者:califeee

本文链接:https://www.cnblogs.com/califeee/p/18690782

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   califeee  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.