2025牛客寒假算法基础集训营4

news/2025/2/6 19:45:22/文章来源:https://www.cnblogs.com/maburb/p/18701592

A. Tokitsukaze and Absolute Expectation

待补


B. Tokitsukaze and Balance String (easy) && C. Tokitsukaze and Balance String (hard)

题意:给你一个01串,有些地方是'?'表示没有填。一个01串的价值看它有多少位置满足取反后整个串10和01的个数相等。求所有可能的01串的价值之和。

这题正解是找规律分类讨论,赛时没多想写了个dp。
手玩一下发现,中间的位置不管怎么变都不会影响10和01的个数。于是如果这个01串本来就是平衡的则贡献为\(n-2\)。然后10的个数和01的个数差值的绝对值不超过1,因为你一个一个往后填01发现,两个01必然贡献一个10,两个10必然贡献一个01。赛时我也是根据这个性质进行的dp。然后发现如果\(s_1 == s_n\)则10和01的个数相等,进行分类讨论就行。中间\(n-2\)个产生的贡献是固定的。
讲讲我的dp解法,\(f[i][0/1][-1/0/1]\),表示第\(i\)个位置填\(0/1\)并且10个数减01个数为\(-1/0/1\)时的方案数,那么答案就是\((f[n][0][0] + f[n][1][0]) \times 2\),然后如果\(s_1 != 0\), 发现只要变化一定使得差值减一,则加上\(f[n][0][1] + f[n][1][1]\),如果\(s_n != 1\),则加上\(f[n][0][0] + f[n][1][0]\)\(s_n\)类似的讨论,其实最后这个讨论就是正解的讨论,我也是写完了才发现\(dp\)了个寂寞。因为有负数下标,第三维都加个1变成\(0/1/2\)

点击查看代码
void solve() {int n;std::cin >> n;std::string s;std::cin >> s;std::vector f(n + 1, std::array<std::array<Z, 3>, 2>{});if (s[0] == '?') {f[1][0][1] = f[1][1][1] = 1;} else if (s[0] == '0') {f[1][0][1] = 1;} else {f[1][1][1] = 1;}for (int i = 1; i < n; ++ i) {if (s[i] != '0') {f[i + 1][1][0] = f[i][1][0] + f[i][0][1];f[i + 1][1][1] = f[i][1][1] + f[i][0][2];f[i + 1][1][2] = f[i][1][2];} if (s[i] != '1') {f[i + 1][0][0] = f[i][0][0];f[i + 1][0][1] = f[i][0][1] + f[i][1][0];f[i + 1][0][2] = f[i][0][2] + f[i][1][1];}}if (n == 1) {std::cout << (f[n][0][1] + f[n][1][1]) << "\n";return;}Z ans = (f[n][0][1] + f[n][1][1]) * (Z)(n - 2);if (s[0] != '0') {ans += f[n][0][2] + f[n][1][2];}if (s[0] != '1') {ans += f[n][0][0] + f[n][1][0];}if (s.back() != '0') {ans += f[n][0][0] + f[n][1][0];}if (s.back() != '1') {ans += f[n][0][2] + f[n][1][2];}std::cout << ans << "\n";
}

D. Tokitsukaze and Concatenate‌ Palindrome

题意:给你两个字符串\(a, b\),你可以将它们都重新排列然后拼接起来。你还可以修改\(a\)里的元素,求让\(a+b\)是回文最小要修改几次。

因为可以重新排列,那么我们尽可能把相同的字符放到对应的位置。然后长串是可以放一些字符到另一边自己和自己匹配的,于是就是统计一下有多少个字符不能匹配,直接除二。因为两边不能匹配的字符数肯定是相等的。如果是奇数个,那么\(a+b\)长度肯定也是奇数,多出来的可以放中间,答案也是直接除二就行。

点击查看代码
void solve() {int n, m;std::cin >> n >> m;std::string s, t;std::cin >> s >> t;std::array<int, 26> cnt{};for (auto & c : s) {cnt[c - 'a'] += 1;}for (auto & c : t) {cnt[c - 'a'] -= 1;}int ans = 0;int tot = std::max(n, m) - (n + m + 1) / 2;for (int i = 0; i < 26; ++ i) {if (cnt[i] < 0 && n <= m) {cnt[i] = -cnt[i];int t = std::min(tot, cnt[i] / 2);cnt[i] -= t * 2;tot -= t;} else if (cnt[i] > 0 && n >= m) {int t = std::min(tot, cnt[i] / 2);cnt[i] -= t * 2;tot -= t;    		}}for (int i = 0; i < 26; ++ i) {ans += std::abs(cnt[i]);}std::cout << ans / 2 << "\n";
}

E. Tokitsukaze and Dragon's Breath

题意:给你一个矩阵,可以选择一个位置得到这个位置所处主对角线和次对角线上所有元素的和。求最大值。

每个主对角线的\(i + j\)相等,每个次对角线的\(i - j\)相等,存下来枚举取那个位置的对角线即可。

点击查看代码
void solve() {int n, m;std::cin >> n >> m;std::vector a(n, std::vector<int>(m));std::vector<i64> sum1((n + m) * 2), sum2((n + m) * 2);for (int i = 0; i < n; ++ i) {for (int j = 0; j < m; ++ j) {std::cin >> a[i][j];sum1[i + j + n + m] += a[i][j];sum2[i - j + n + m] += a[i][j];}}i64 ans = 0;for (int i = 0; i < n; ++ i) {for (int j = 0; j < m; ++ j) {ans = std::max(ans, sum1[i + j + n + m] + sum2[i - j + n + m] - a[i][j]);}}std::cout << ans << "\n";
}

F. Tokitsukaze and Kth Problem (easy)

待补


G. Tokitsukaze and Kth Problem (hard)

待补


H. Tokitsukaze and Necklace

待补。


I. Tokitsukaze and Pajama Party

题意:求每个"uwawauwa"前面有多少"u"。

模拟统计即可。

点击查看代码
void solve() {int n;std::cin >> n;std::string s;std::cin >> s;std::string t = "uwawauwa";int len = t.size();i64 ans = 0, cnt = 0;for (int i = 0; i + len - 1 < n; ++ i) {if (s.substr(i, len) == t) {ans += cnt;}if (i > 0 && s[i - 1] == 'u') {++ cnt;}}std::cout << ans << "\n";
}

J. Tokitsukaze and Recall

题意:有若干个联通块,你可以选\(k\)个点,可以随时传送到这\(k\)个点的任意一个。你要占领尽可能多的点。并给出移动方案。要求字典序最小。

首先求出所有连通块。设有\(cnt\)个。
要占领尽可能的点,那么我们肯定先联通块大小从大到小的给每个联通块一个传送点,如果大小相同,则最小点更小的优先。然后可以搜索方案,我们给每个联通块最小的点一个传送点,然后我们用优先级队列来搜索使得我们每次可以走编号最小的点。如果还有多余的传送点,并且当前到的点不是可以到的剩余点里的最小的,那么可以给这个剩余点里最小的点一个传送点。模拟即可。

点击查看代码
struct DSU {std::vector<int> fa, cnt;DSU(int _n) {init(_n);}void init(int _n) {fa.assign(_n + 1, 0);cnt.assign(_n + 1, 1);std::iota(fa.begin(), fa.end(), 0);}int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}bool merge(int x, int y) {x = find(x), y = find(y);if (x == y) {return false;}fa[y] = x;cnt[x] += cnt[y];return true;}bool same(int x, int y) {return find(x) == find(y);}int size(int x) {return cnt[find(x)];}
};void solve() {int n, m, k;std::cin >> n >> m >> k;std::vector<std::vector<int>> adj(n);DSU d(n);for (int i = 0; i < m; ++ i) {int u, v;std::cin >> u >> v;-- u, -- v;if (u > v) {std::swap(u, v);}adj[u].push_back(v);adj[v].push_back(u);d.merge(u, v);}std::vector<std::vector<int>> blocks(n);int cnt = 0;for (int i = 0; i < n; ++ i) {blocks[d.find(i)].push_back(i);cnt += d.find(i) == i;}std::sort(blocks.begin(), blocks.end(), [&](std::vector<int> & a, std::vector<int> & b) {if (a.size() && b.size() && a.size() == b.size()) {return a[0] < b[0];}return a.size() > b.size();});int t = std::min(k, cnt);k = std::max(0, k - cnt);std::priority_queue<int, std::vector<int>, std::greater<int> > heap;std::vector<int> st(n);std::set<int> s;for (int i = 0; i < t; ++ i) {for (auto & x : blocks[i]) {s.insert(x);}heap.push(blocks[i][0]);st[blocks[i][0]] = 1;}std::vector<int> ans;while (heap.size()) {if (heap.top() != *s.begin() && k > 0) {-- k;heap.push(*s.begin());st[*s.begin()] = 1;}int u = heap.top(); heap.pop();s.erase(u);ans.push_back(u);for (auto & v : adj[u]) {if (!st[v]) {st[v] = 1;heap.push(v);}}}std::cout << ans.size() << "\n";for (auto & x : ans) {std::cout << x + 1 << " \n"[x == ans.back()];}
}

K. Tokitsukaze and Shawarma

签到题。

点击查看代码
void solve() {int x, y, z, a, b, c;std::cin >> x >> y >> z >> a >> b >> c;std::cout << std::max({x * a, y * b, z * c}) << "\n";
}

L. Tokitsukaze and XOR-Triangle

题意:多次询问求一个区间内两两异或和的和。

按位计算,那么就变成了在一个01串里询问一个区间里有多少01和10。
可以前缀和求出来每个位置和它前面的数产生了多少贡献。但求\([l, r]\)时,发现\(sum_r - sum_{l-1}\)这个贡献里\([l, r]\)里数算上了\([1, l - 1]\)这些数产生的贡献,考虑减去,设\([1, l - 1]\)\(cnta0\)个0,\(cnta1\)个1,\([l, r]\)里有\(cntb0\)个0,\(cntb1\)个1。那么需要减去的贡献为\(cnta0 \times cntb1 + cnta1 \times cntb0\)

点击查看代码
void solve() {int n, q;std::cin >> n >> q;std::vector<i64> a(n + 1), b(n + 1);for (int i = 1; i <= n; ++ i) {std::cin >> a[i];}for (int i = 1; i <= n; ++ i) {std::cin >> b[i];}std::vector suma(n + 1, std::array<i64, 30>{});std::vector sumb(n + 1, std::array<i64, 30>{});for (int i = 1; i <= n; ++ i) {suma[i] = suma[i - 1];sumb[i] = sumb[i - 1];for (int j = 0; j < 30; ++ j) {suma[i][j] += a[i] >> j & 1;sumb[i][j] += b[i] >> j & 1;}}std::vector sum(n + 1, std::array<i64, 30>{});for (int i = 1; i <= n; ++ i) {sum[i] = sum[i - 1];for (int j = 0; j < 30; ++ j) {if (b[i] >> j & 1) {sum[i][j] += i - suma[i][j];} else {sum[i][j] += suma[i][j];}}}for (int i = 0; i < q; ++ i) {int l, r;std::cin >> l >> r;Z ans = 0;for (int i = 0; i < 30; ++ i) {i64 cnta1 = suma[l - 1][i], cnta0 = l - 1 - cnta1;i64 cntb1 = sumb[r][i] - sumb[l - 1][i], cntb0 = r - l + 1 - cntb1;ans += (Z)(1ll << i) * (sum[r][i] - sum[l - 1][i] - cnta1 * cntb0 - cnta0 * cntb1);}std::cout << ans << "\n";}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/879784.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《高效能人士的七个习惯》

情感账户 勇气和体谅 大石头 自传式回应、同理心倾听:用你的话反映他们的感受和意思,而不是去评论、去判断是否正确

高效能人士的七个习惯

情感账户 勇气和体谅 大石头 自传式回应、同理心倾听:用你的话反映他们的感受和意思,而不是去评论、去判断是否正确

新春“码”启 | Cocos 3D 微信小游戏(第5天):分包构建和上传发布(完美收官)

新春开发 Cocos 3D 微信小游戏计划的第 5 天,详细介绍了如何利用Cocos Creator开发并发布一款3D微信小游戏,包括游戏状态机的设计理念,和微信小游戏主包大小限制时的解决方案——分包策略。从游戏设计、开发、调试到最后成功发布的全过程,为想要进入微信小游戏开发领域的开…

爬虫随笔(一)

爬虫随笔,某牛前几天一直在看js逆向,现在分享一下本人近期学习记录首先分享一个网站,这个网站可以获得request所需要的header和cookie https://curlconverter.com/ 爬取网站就不挂了简单观察发现,该网站是滑动加载,我们可以在滑动加载时获得我们所需要的接口,发现两个链…

Flow-CLI 全新升级,轻松对接 Sonar 实现代码扫描和红线卡点

Flow-CLI 使用的典型场景如:自定义开发一个 Sonar 扫描步骤,以在流水中触发 Sonar 扫描,并以扫描结果作为红线卡点,以保证代码质量;对接三方自有审批平台,在发布前进行检查审批,审批通过才允许发布。场景介绍 Flow-CLI 是云效流水线 Flow 推出的一款命令行工具,帮助用户…

皮克定理

小蓝鸟的面积S=B/2+I-1

两步构建 AI 总结助手,实现智能文档摘要

本次解决方案将向您介绍,如何通过函数计算 FC 阿里云百炼平台搭建智能 AI 总结助手,实现高效的文本自动总结和信息提取。在信息极度丰富的当下,如何从海量且复杂的文件资料中筛选出关键内容,成为了不少企业和个人急需解决的问题。本次解决方案将向您介绍,如何通过函数计算…

自定义桌面——获取天气

最近天气时不时会降温,经常用手机查看天气,感觉好不方便,今天决定把天气的功能添加到“自定义桌面”来,为了免费获取天气数据,竟然花了差不多一天的时间来制作完成。(假如一天人工费几百来算,这样真的值得吗?非常值得!为未来完善功能添砖加瓦打好基础!) 添加天气的功…

2.6 第三张评估表搭建

今天完成了作业中第三张能力评估表的搭建 html界面(部分)如下:以下是前端代码(部分): <body> <h1 style="text-align: center">能力评估</h1> <div id="root" style="border: 1px solid black"><form id="…

V-Control 开箱即用的.NET MAUI组件库发布了!

之前写过挺多的MAUI Sample,其中有很多代码可以打包成组件,当组件完善到一定程度,我会把控件封装起来放到控件库中。 今天,在这个仓库建立一年零八个月后,我觉得可以考虑将其作为开源库发布。 有很多网友在观望.NET MAUI,犹豫是否可以拿来作为有生产力的跨平台移动端开发…

国产直升机发展现状及思考

​由于独特的自然环境条件以及当前经济社会发展情况,比较世界上其他发达国家,直升机早已渗入中国城乡建设与经济社会活动的各个环节,例如农林工作、地质勘探、旅游观光、飞机驾驶训练等,直升机对国民经济工程建设起到了重要的作用。 按照我国航空工业技术研究机构的预计,截…

做题随笔:P10451

Solution 题意 原题链接 定义二元关系 \(\text{S}\),其满足反对称性且不满足传递性。 现有互异元素 \(N(N \le 1000)\) 个,可以进行不多于 \(10000\) 次提问,每次提问可以得知两指定元素 \(a,b\) 的 \(a \, \text{S} \, b\) 结果。求序列 \(a_N\) 满足:对任意 \(x_i,x_{i+1…