当前位置: 首页 > news >正文

2024.7.20 暑期训练记录(6)

CF

1391D - 505(思维+状压dp)

  • 首先简化问题,发现一个矩阵如果要满足条件,那它其中的每一个 2 × 2 2\times 2 2×2 的小矩阵都要满足条件,于是很容易发现 4 × 4 4\times4 4×4 的矩阵是一定不满足条件的(因为是由四个 2 × 2 2\times2 2×2 的矩阵拼起来的,所以里面的 1 1 1 一定是偶数个),既然如此,更大的矩阵就更不行了,因为里面肯定会包含 4 × 4 4\times4 4×4 的矩阵,所以就把问题简化到 n ≤ 3 n\le3 n3 的情况了
  • n = 1 n=1 n=1 时,没有边长为偶数的子矩阵,所以一定是好矩阵
  • n = 2 n=2 n=2 时,枚举一下第一列有 0 / 1 / 2 0/1/2 0/1/2 1 1 1 的情况,取最小操作数
  • n = 3 n=3 n=3 时,状压dp,用二进制表示每一列的情况, d p [ i ] [ j ] dp[i][j] dp[i][j] 表示第 i i i 列变成状态 j j j 的最小操作数,转移方程 d p [ i ] [ j ] = min ⁡ ( d p [ i ] [ j ] , d p [ i − 1 ] [ k ] + c h a n g e ( i , j ) ) dp[i][j]=\min(dp[i][j],\ dp[i-1][k]+change(i, j)) dp[i][j]=min(dp[i][j], dp[i1][k]+change(i,j)) (如果 k k k j j j 状态合法)
#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, m;cin >> n >> m;vector<vector<char>> g(n + 1, vector<char>(m + 1));for (int i = 1; i <= n; i ++ )for (int j = 1; j <= m; j ++ )cin >> g[i][j];if (n >= 4) cout << -1 << '\n';else if (n == 1) cout << 0 << '\n';else if (n == 2){vector<int> cnt(m + 1);for (int i = 1; i <= m; i ++ ){int tmp = 0;for (int j = 1; j <= n; j ++ ){if (g[j][i] == '1') tmp ++ ;}cnt[i] = tmp;}vector<int> ans(3);for (int k = 0; k < 3; k ++ ){ans[k] += abs(cnt[1] - k);int lst = k;for (int i = 2; i <= m; i ++ ){if (lst & 1){if (cnt[i] & 1) ans[k] ++ ;lst = 0;}else{if (cnt[i] % 2 == 0) ans[k] ++ ;lst = 1;}}}cout << min({ans[0], ans[1], ans[2]}) << '\n';}else if (n == 3){// 将每一列转化成二进制vector<int> mp(m + 1);for (int i = 1; i <= m; i ++ ){int tmp = 0;for (int j = 1; j <= n; j ++ ){if (g[j][i] == '1') tmp += (1ll << (j - 1));}mp[i] = tmp;}// 转化步数auto change = [&](int a, int b){int state = (a ^ b);int ans = 0;for (int i = 0; i < 3; i ++ ){if ((state >> i) & 1) ans ++ ;}return ans;};// 判断相邻状态合法性auto check = [&](int a, int b){int a1 = ((a >> 0) & 1), a2 = ((a >> 1) & 1), a3 = ((a >> 2) & 1);int b1 = ((b >> 0) & 1), b2 = ((b >> 1) & 1), b3 = ((b >> 2) & 1);if ((a1 + a2 + b1 + b2) % 2 == 0) return false;if ((a2 + a3 + b2 + b3) % 2 == 0) return false;return true; };// 初始化vector<vector<int>> dp(m + 1, vector<int>(8, INF));for (int i = 0; i < 8; i ++ ) dp[1][i] = change(mp[1], i);for (int i = 2; i <= m; i ++ ){for (int j = 0; j < 8; j ++ ) // i-1列的状态{for (int k = 0; k < 8; k ++ ) // i列的状态{if (!check(j, k)) continue; // jk作为相邻状态不合法dp[i][k] = min(dp[i][k], dp[i - 1][j] + change(mp[i], k));}}}int ans = INF;for (int i = 0; i < 8; i ++ ) ans = min(ans, dp[m][i]);if (ans == INF) cout << -1 << '\n';else cout << ans << '\n';}
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t--){solve();}
}

1296E2 - String Coloring (hard version)(思维+dp)

  • 首先想一想什么情况下需要交换呢,即一个字母在另一个字母前面,但是前面的字母比后面的字母大的时候,也就是说,涂同一种颜色的位置必须是单调不减的,我们把涂同一种颜色的位置放在一个集合里,可以证明,所有集合的最后一个位置上的字符一定是单调递减的(感性理解一下,如果有递增的,那直接放到前一个集合就好了,没必要放在下一个集合)所以问题就转化成了求最长下降子序列
  • 应该是一个经典的trick,可以积累一下
  • d p [ i ] dp[i] dp[i] 表示从 [ i , n ] [i,\ n] [i, n] 的最长下降子序列长度, m a x x [ i ] maxx[i] maxx[i] 表示从字母 i + ′ a ′ i+'a' i+a ′ z ′ 'z' z 开头的最长下降子序列长度
#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n; cin >> n;string s; cin >> s;s = " " + s;vector<int> dp(n + 1);vector<int> maxx(26);int ans = 0;for (int i = n; i >= 1; i -- ){int c = s[i] - 'a';dp[i] = maxx[c] + 1;for (int j = c + 1; j < 26; j ++ ) maxx[j] = max(maxx[j], dp[i]);ans = max(ans, dp[i]);}cout << ans << '\n';for (int i = 1; i <= n; i ++ ) cout << dp[i] << ' ';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t--){solve();}
}

1616D - Keep the Average High(思维)

  • 好聪明的做法,先把所有数都减去 x x x,这样需要满足的条件就是 a l + a r > = 0 a_l+a_r>=0 al+ar>=0
  • 然后只需要看连续的长度为 2 2 2 的串和长度为 3 3 3 的串是否满足条件就好了,为什么只需要看这两种呢,因为其他长度的串都可以用这两种拼起来啊,这种想法在今天的第一道 dp 中已经出现过了
#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n; cin >> n;vector<int> a(n + 1);for (int i = 1; i <= n; i ++ ) cin >> a[i];int x; cin >> x;for (int i = 1; i <= n; i ++ ) a[i] -= x;int ans = n;for (int i = 2; i <= n; i ++ ){if (a[i] + a[i - 1] + a[i - 2] < 0 || a[i] + a[i - 1] < 0){ans -- ;a[i] = INF;}}cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t--){solve();}
}

1978D - Elections(思维+前缀后缀)

  • 贪心一下,想赢的话先删前面的人,前面的人删了还赢不了就删掉后面最大的
#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, c;cin >> n >> c;vector<int> a(n + 1);vector<int> pre(n + 1), maxx_pre(n + 1), maxx_suff(n + 2);for (int i = 1; i <= n; i ++ ) cin >> a[i];for (int i = 1; i <= n; i ++ ) pre[i] = pre[i - 1] + a[i];for (int i = 1; i <= n; i ++ ) maxx_pre[i] = max(maxx_pre[i - 1], a[i]);for (int i = n; i >= 1; i -- ) maxx_suff[i] = max(maxx_suff[i + 1], a[i]);for (int i = 1; i <= n; i ++ ){if (i == 1){if (a[i] + c >= maxx_suff[i + 1]) cout << 0 << ' ';else cout << 1 << ' ';}else if (i == n){if (a[i] > max(maxx_pre[i - 1], a[1] + c)) cout << 0 << ' ';else cout << n - 1 << ' ';}else{if (a[i] > max(a[1] + c, maxx_pre[i - 1])){if (a[i] >= maxx_suff[i + 1]) cout << 0 << ' ';else{if (a[i] + pre[i - 1] + c >= maxx_suff[i + 1]) cout << i - 1 << ' ';else cout << i << ' ';}}else{if (a[i] + pre[i - 1] + c >= maxx_suff[i + 1]) cout << i - 1 << ' ';else cout << i << ' ';}}}cout << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t--){solve();}
}

1979D - Fixing a Binary String(思维)

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<int, char> PIC;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
typedef pair<int, pair<int, bool>> PIIB;const int N = 1e6 + 10;
const int maxn = 1e6 + 10;
const int mod = 1e9 + 7;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, k;cin >> n >> k;string s;cin >> s;vector<int> a(1);int tmp = 1;for (int i = 1; i < n; i ++ ){if (s[i] != s[i - 1]){a.push_back(tmp);tmp = 1;}else tmp ++ ;}if (tmp != 0) a.push_back(tmp);int pos = -1;int m = a.size() - 1;vector<int> pre(m + 1);for (int i = 1; i <= m; i ++ ) pre[i] = pre[i - 1] + a[i];for (int i = 1; i <= m - 1; i ++ ){if (a[i] != k){if (pos == -1) pos = i;else{cout << -1 << '\n';return;}}}if (pos == -1){if (a[m] == k) cout << n << '\n';else cout << -1 << '\n';}else{if (a[m] == k){if ((m % 2 == 0 && pos % 2 == 0) || (m % 2 != 0 && pos % 2 != 0)){cout << -1 << '\n';}else{if (a[pos] == 2 * k) cout << pre[pos - 1] + k << '\n';else cout << -1 << '\n';}}else{if (a[m] > k) cout << -1 << '\n';else{int tmp = k - a[m];if ((m % 2 == 0 && pos % 2 == 0) || (m % 2 != 0 && pos % 2 != 0)){if (a[pos] >= tmp && ((a[pos] - tmp) == k || (a[pos] - tmp) == 0)) cout << pre[pos - 1] + tmp << '\n';else cout << -1 << '\n';}else cout << -1 << '\n';}}}
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t--){solve();}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • pytest钩子hook使用2
  • Webpack详解
  • 网络抓包工具tcpdump的使用
  • 持续集成03--Jenkins的安装与配置
  • 【AI工具基础】—B树(B-tree)
  • Llama - 量化
  • Bubbliiiing 的 Retinaface rknn python推理分析
  • git使用总结
  • PV(Page View)、UV(Unique Visitor)和IP(Internet Protocol)
  • 【前端】Babel详解
  • 【网络安全科普】勒索病毒 防护指南
  • 9.11和9.9哪个大?
  • FOG Project 文件名命令注入漏洞复现(CVE-2024-39914)
  • Qt Creator配置以及使用Valgrind - 检测内存泄露
  • vscode 打开远程bug vscode Failed to parse remote port from server output
  • Android Studio:GIT提交项目到远程仓库
  • dva中组件的懒加载
  • golang 发送GET和POST示例
  • LintCode 31. partitionArray 数组划分
  • mac修复ab及siege安装
  • react-native 安卓真机环境搭建
  • SAP云平台里Global Account和Sub Account的关系
  • vue:响应原理
  • yii2中session跨域名的问题
  • 代理模式
  • 给Prometheus造假数据的方法
  • 解析带emoji和链接的聊天系统消息
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 为视图添加丝滑的水波纹
  • #NOIP 2014# day.2 T2 寻找道路
  • #Spring-boot高级
  • (1)常见O(n^2)排序算法解析
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (6)STL算法之转换
  • (7)摄像机和云台
  • (函数)颠倒字符串顺序(C语言)
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (南京观海微电子)——COF介绍
  • (三)Pytorch快速搭建卷积神经网络模型实现手写数字识别(代码+详细注解)
  • (最完美)小米手机6X的Usb调试模式在哪里打开的流程
  • **python多态
  • .NET Compact Framework 多线程环境下的UI异步刷新
  • .net core使用ef 6
  • .Net 垃圾回收机制原理(二)
  • :class的用法及应用
  • @ModelAttribute 注解
  • @RequestBody与@RequestParam
  • @取消转义
  • [ vulhub漏洞复现篇 ] JBOSS AS 5.x/6.x反序列化远程代码执行漏洞CVE-2017-12149
  • [<死锁专题>]
  • [20180129]bash显示path环境变量.txt
  • [2023-年度总结]凡是过往,皆为序章
  • [C#] 基于 Token 的鉴权与签名机制详解 接口对接鉴权 token、sign(a=1b=2c=3d=4)、Base64、参数加密、MD5
  • [EFI]ASUS Vivobook 16x M1603QA 电脑 Hackintosh 黑苹果efi引导文件
  • [Git 1]基本操作与协同开发