codeforces一些题目思路复盘

codeforces round 919 dv2 C Partitioning the Array

大致题意,对于n约数i,我们把原数组分成\frac{n}{i}份,并且每份中有i个元素,对于每个分组情况,如果存在一个数m使得数组中元素modm后使得每个部分的数组完全相同,如果存在那么ans ++求ans

这是一道数论题,数论题的关键在于将数学问题用数学公式表示出来,现在考虑如果存在一个数组a_1a_2a_3a_4....a_n是否存在一个整数m使得数组amodm后所有元素相同

对于这个简化的问题首先列出数学公式 对于i\epsilon[1, n]j\epsilon[1, n] i \neq j 有 a_i\equiv a_j modm

对这个同余式子移项后可得到|a_i - a_j|\equiv 0modm,对于这个式子我们得到这样一个结论|a_i - a_j|是可以整除m的。当然m不能为1,现在把这个式子拓展到整个数组,那么就有了所有相邻元素相减的绝对值都应该整除m,并且m不为1,换句话说这些数两两不互质。当然m的最大值就是这些数的gcd了(codeforces round991 div3 F Maximum modulo equality)。

现在再回到这个问题上,这个问题就相当于这个m必须同时满足很多个数组(\frac{n}{i}个,每个子数组中的元素)每个数组求出gcd中,再将这些gcd求总共gcd,只要gcd不为1,就说明ans可以++。当然这里也涉及到时间复杂度的计算,首先的约数预处理O(n\sqrt{n})最外层的for是约数个数,数据范围内最大的约数个数为168个,总之约数的个数都很小。紧接着的两重循环不大会算,但是感觉可以过:(

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const int N = 2e5 + 10;int gcd(int a, int b) {return b? gcd(b, a % b): a;
}void solve() {int n;cin >> n;vector<int> a(n + 1);for(int i = 1; i <= n; i ++ ) cin >> a[i];vector<int> divi;for(int i = 1; i <= n / i; i ++ ) {if(n % i == 0) {divi.push_back(i);if(n / i != i) divi.push_back(n / i);}}int ans = 1;for(auto t: divi) {//168bool ok = true;if(t == n) continue;else {vector<int> alls;for(int i = 1; i <= t; i ++ ) {int _gcd = -1;for(int j = i + t; j <= n; j += i ) {if(_gcd == -1) _gcd = abs(a[j] - a[j - t]);else _gcd = gcd(_gcd, abs(a[j] - a[j - t]));}alls.push_back(_gcd);}int _gcd = -1;for(auto t: alls) {if(_gcd == -1) _gcd = t;else _gcd = gcd(t, _gcd);}if(_gcd == 1) ok = false;}if(ok) ans ++;}cout << ans << "\n";
}int main() {ll t;cin >> t;while(t -- ) solve();return 0;
}

codeforces round914div2 C array game

这道题是个tips题,注意到当k大于3时答案总是0,在遇到无从下手的题目时一定要试着去寻找一些特判情况,将答案简化

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const ll INF = 1e18;void solve() {ll n, k;cin >> n >> k;vector<ll> a(n + 1);ll minv = INF;for(int i = 1; i <= n; i ++ ) {cin >> a[i];minv = min(minv, a[i]);}sort(a.begin() + 1, a.end());ll ans = INF;if(k > 2) {cout << "0\n";return;} else if(k == 1) {for(int i = 1; i <= n; i ++ ) {for(int j = 1; j <= n; j ++ ) {if(i == j) continue;ans = min(ans, abs(a[i] - a[j]));}}} else if(k == 2) {for(int i = 1; i <= n; i ++ ) {for(int j = i + 1; j <= n; j ++ ) {if(i == j) continue;ll del = a[j] - a[i];int l = 1, r = n;while(l < r) {int mid = l + r >> 1;if(a[mid] >= del) r = mid;//找到第一个大于等于del的数else l = mid + 1;}ans = min(ans, abs(a[l] - del));ans = min(ans, abs(a[l - 1] - del));}}}cout << min(ans, minv) << "\n";
}int main() {ll t;cin >> t;while(t -- ) solve();return 0;
}

D set to max

题目大意:给出两个数组,a,b,每次可以从a中任意选择一段区间,并且把区间中元素赋值成区间最大值,easy version和hard version的区别就在于数据范围,有经验的话会立刻明白这个数据范围的作用就是限制求区间最值时的方式,时间复杂度O(n^2)允许的话可以直接暴力求解,反之则可以用线段树维护。现在去思考如何解决这个问题:为了方便我们对数据进行处理,把目标区间取出来是必要的。现在考虑方案的可行性,下述区间的表述都是取出来的区间段,即对于一个区间段的任意l,r,满足b[l] = b[r]。如果a中该区间段最大值大于了该区间中b的值(设为x),那么直接判负,因为较大数值会覆盖较小的数值.。同样的如果想要赋值成x,就要保证a数组中存在x,并且在达到x之前没有比x更大的数。这样就结束了吗,上文中提到了,较大值会覆盖最小值,倘若在枚举到当前区间前维护的区间的x比该区间的x要大,并且恰好我这个区间所需要的值被覆盖掉了,那么会导致可行的方案被判否,因此要贪心的以x值较小的区间开始维护,并且在以后的维护中,如果在a中的x必须跨越先前已经维护过的区间,那么答案就会被判否(因为会将以前维护好的覆盖掉)

现在思路就明朗了,时间复杂度O(nlogn)整体可控

代码:
 

#include <bits/stdc++.h>
using namespace std;typedef long long ll;
const int INF = 0x3f3f3f3f;void solve() {int n;cin >> n;vector<int> a(n + 2), b(n + 1);for(int i = 1; i <= n; i ++ ) cin >> a[i];for(int i = 1; i <= n; i ++ ) cin >> b[i];map<int, int> ma;a[0] = a[n + 1] = INF;vector<int> L(n + 1), R(n + 1);for(int i = 1; i <= n; i ++ ) {if(ma[b[i]] == 0) L[i] = 0;else L[i] = ma[b[i]];ma[a[i]] = i;}ma.clear();for(int i = n; i >= 1; i -- ) {if(ma[b[i]] == 0) R[i] = n + 1;else R[i] = ma[b[i]];ma[a[i]] = i;}struct node {int l, r, val, tag;bool operator < (const node &W) {return val < W.val;}};vector<node> tr(n * 4 + 1);auto pushup = [&](int u) {tr[u].val = max(tr[u << 1].val, tr[u << 1 | 1].val);};function<void(int, int, int)> build = [&](int u, int l, int r) {tr[u].l = l, tr[u].r = r;if(l == r) return;int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);};function<void(int, int)> insert = [&](int u, int pos) {if(tr[u].l == tr[u].r && tr[u].l == pos) tr[u].val = a[pos];else {int mid = tr[u].l + tr[u].r >> 1;if(mid >= pos) insert(u << 1, pos);if(mid < pos) insert(u << 1 | 1, pos);pushup(u);}};function<int(int, int, int)> query = [&](int u, int l, int r) {if(tr[u].l >= l && tr[u].r <= r) return tr[u].val;else {int res = 0;int mid = tr[u].l + tr[u].r >> 1;if(mid >= l) res = query(u << 1, l, r);if(mid < r) res = max(res, query(u << 1 | 1, l, r));return res;}};build(1, 1, n);for(int i = 1; i <= n; i ++ ) insert(1, i);vector<node> st(4 * n + 1);function<void(int, int, int)> build1 = [&](int u, int l, int r) {st[u].l = l, st[u].r = r;if(l == r) return;int mid = l + r >> 1;build1(u << 1, l, mid);build1(u << 1 | 1, mid + 1, r);};auto pushup1 = [&](int u) {st[u].val = st[u << 1].val | st[u << 1 | 1].val;    };auto pushdown = [&](int u) {st[u << 1].val |= st[u].tag;st[u << 1].tag |= st[u].tag;st[u << 1 | 1].val |= st[u].tag;st[u << 1 | 1].tag |= st[u].tag;st[u].tag = 0;};function<void(int, int, int)> insert1 = [&](int u, int l, int r) {if(st[u].l >= l && st[u].r <= r) {st[u].val = 1;st[u].tag = 1;} else {pushdown(u);int mid = st[u].l + st[u].r >> 1;if(mid >= l) insert1(u << 1, l, r);if(mid < r) insert1(u << 1 | 1, l, r);pushup1(u);}};function<int(int, int, int)> query1 = [&](int u, int l, int r) {if(st[u].l >= l && st[u].r <= r) return st[u].val;else {int res = 0;int mid = st[u].l + st[u].r >> 1;if(mid >= l) res = query1(u << 1, l, r);if(mid < r) res |= query1(u << 1 | 1, l, r);return res;}};build1(1, 1, n);vector<node> pos;int i = 1, j = 1;while(i <= n && j <= n) {while(j <= n && b[i] == b[j]) j ++;pos.push_back({i, j - 1, b[i]});i = j;}//cout << L[4] << " ";sort(pos.begin(), pos.end());for(int k = 0; k < pos.size(); k ++ ) {auto t = pos[k];int l = t.l, r = t.r, x = t.val;//cout << l << " " << r << " " << x << "\n";int max_val = query(1, l, r);if(max_val > x) {cout << "NO\n";return;}if(max_val == x) {insert1(1, l, r);continue;}bool ok1 = false;bool ok2 = false;if(a[L[l]] == x && !query1(1, L[l], l) && (query(1, L[l], l) == x)) ok1 = true;if(a[R[r]] == x && !query1(1, r, R[r]) && (query(1, r, R[r]) == x)) ok2 = true;if(!ok1 && !ok2) {cout << "NO\n";return;} else {/*for(int i = l; i <= r; i ++ ) insert1(1, i);*/insert1(1, l, r);}}//cout << query1(1, 1, 2) << " ";cout << "YES\n";
}int main() {int t;cin >> t;while(t -- ) solve();return 0;
}

codeforces round 932 div2 C find a mine

这是一道交互题,这道题这道题启示我到一个点的曼哈顿距离相等的所有点的路径是个菱形(如果没有超过图的边界的话)

D1. XOR Break — Solo Version

题目大意:对于x我们可以将x设为y或者xXORy并且满足y < x并且xXory < x问是否可以将x变成m(m < x)

数据范围很大,并且有xor操作,直接考虑拆位

现在似乎仍然无从下手,那么试着挖掘一些隐含在题目中的性质

m小于x试着考虑一下这个条件的性质:

容易得到,如果xy满足小于关系那么有

x: same 1 ??????

m:same 0 ??????

从高位起第一位不同的二进制表示,x为1,m为0

再考虑如果x Xor y < x要满足什么条件

x:             same 1 ??????

y          :  00000 1 ??????

m         :  same   0 ??????(x xor y = m)

其实这里可以注意到如果same存在1的话,那么后面的????填什么都可以因为y肯定比x小并且m本来就比x小,现在要讨论的情况就是same全为0的情况。如果m的?号位为0的话,那么x和y的?号位要相同,不是0就是1,反之?号位不同,也就是说,如果在same 1以后的二进制表示位中,如果m中出现的第一个1对应的x中二进制中表示位是1的话,那么我们同样可以将x转化为m,反之就证明当前的y比x要小,不满足题意,这时候我们要考虑是否可以借助一个中间值转化一下,使得这一位的值变成1(借位),借位只能向1借,并且不能same后面的那位1实际上是不能动的,这里可以手动模拟一下,也就是说,如果在same1后面的二进制位到该位之间x二进制表示位为1的话,我们就可以借助这个中间值将其转化为上述的情况。(可以找个较小的数值模拟一下)

代码:

#include <bits/stdc++.h>
using namespace std;typedef long long ll;void solve() {ll n, m;cin >> n >> m;bool ok = 0;ll pos = -1;for(ll i = 62; i >= 0; i -- ) {if(n >> i & 1) {if(!(m >> i & 1)) {pos = i;break;}}if(n >> i & 1) ok = true;}//cout << pos << "LL";if(ok) {cout << "1\n";cout << n << " " << m << "\n";} else {bool flag = false;for(ll i = pos - 1; i >= 0; i -- ) {if(m >> i & 1) {if(n >> i & 1) {flag = true;break;}if(!(n >> i & 1)) break;}}if(flag) {cout << "1\n";cout << n << " " << m << "\n";} else {/*0 0 0 0 0 1 a b c 00 0 0 0 0 1 a b c 10 0 0 0 0 0 0 0 0 1*/ll pos1 = -1;for(ll i = pos - 1; i >= 0; i -- ) {if(m >> i & 1) break;if(n >> i & 1) {pos1 = i;break;}}if(pos1 == -1) cout << "-1\n";else {cout << "2\n";ll res = n;ll now = 1ll << pos;for(ll i = 62; i >= pos; i -- ) {res -= (n >> i & 1) * (1ll << i);}for(ll i = pos1 - 1; i >= 0; i -- ) {if((m >> i & 1) && !(n >> i & 1)) {res += 1ll << i;break;}}cout << n << " " << res << " " << m << "\n";}}}
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);ll t;cin >> t;while(t -- ) solve();return 0;
}

codeforces round 991 div3 G

题目大意,从一颗树中删除一条链,找到删除后联通块数量的最大值

树类的问题,直接考虑dfs,树形dp

首先有一个很重要的性质,路径一定要尽可能多的删(除了叶子节点),并且每个点的贡献与这个点的临边数量有关,其实思考一下就是树的直径,只不过把边权换成了点权...

这里说一下树的直径:

代码:
 

#include <bits/stdc++.h>
using namespace std;typedef long long ll;void solve() {int n;cin >> n;vector<vector<int>> adj(n + 1);for(int i = 2; i <= n; i ++ ) {int u, v;cin >> u >> v;adj[u].push_back(v);adj[v].push_back(u);}vector<int> dp(n + 1);int ans = 0;function<void(int, int)> dfs = [&](int u, int fa) {int tot = adj[u].size();dp[u] = max(0, tot - 2);int fir = -1, sec = -1;bool flag = true;for(auto t: adj[u]) {if(t == fa) continue;flag = false;dfs(t, u);dp[u] = max(dp[u], tot - 2 + dp[t]);if(dp[t] >= fir) {sec = fir;fir = dp[t];} else if(dp[t] >= sec) {sec = dp[t];}int res = max(0, fir) + max(0, sec);if(tot == 1) res ++;else if(tot > 2) res += tot - 2;ans = max(res, ans);}if(flag) dp[u] = 1;};if(n == 2) cout << "1\n";else {dfs(1, 1);cout << ans << "\n";}
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t;cin >> t;while(t -- ) solve();return 0;
}

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

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

相关文章

ElasticSearch 简介

一、什么是 ElastcSearch&#xff1f; ElasticSearch 是基于 Lucene 的 Restful 的分布式实时全文搜索引擎。 1.1 ElasticSearh 的基本术语概念 index 索引 索引类似与 mysql 中的数据库&#xff0c;ES 中的索引是存储数据的地方&#xff0c;包含了一堆有相似结构的文档数据…

Please activate LaTeX Workshop sidebar item to render the thumbnail of a PDF

Latex代码中使用pdf图片&#xff0c;无法预览&#xff0c;提示&#xff1a; Please activate LaTeX Workshop sidebar item to render the thumbnail of a PDF 解决办法&#xff1a; 点击左边这个刷新下即可

测试工程师的职业规划

测试人员在管理上的发展 基层测试管理者&#xff1a;测试组长 工作内容&#xff1a;安排小组工作&#xff0c;提升小组成员测试能力&#xff0c;负责重要的测试工作。 负责对象&#xff1a;版本&#xff0c;项目 中层测试管理者&#xff1a;测试经理 负责对象&#xff1…

Linux系统下多任务管理器:screen使用指南

文章目录 安装快速入门启动Screen会话创建和管理窗口退出和恢复会话 高级功能多用户支持日志记录复制粘贴模式自定义配置 在Linux和类Unix系统的世界里&#xff0c;命令行是用于与系统交互的主要方式之一。然而&#xff0c;当涉及到远程服务器管理、长时间运行的任务或者同时处…

C缺陷与陷阱 — 8 编译与链接

目录 1 程序的编译过程 2 动态链接的优缺点 2.1 动态链接的优点 2.2 动态链接的缺点 2.3 只使用动态链接 3 函数库链接的5个特殊秘密 4 警惕Interpositioning 5 产生链接器报告文件 1 程序的编译过程 程序的编译过程是将源代码转换成计算机可以执行的机器代码的过程。…

Harmony Next开发Navigation页面跳转

概述 Harmony Next开发Navigation页面跳转 知识点 Navigation通过NavPathStack路由跳转Navigation以弹窗的方式打开NavDestination页面Menu配置 组件 NavTest Entry Component struct NavTest {Provide pageInfos: NavPathStack new NavPathStack()Builder PageMap(name…

大模型系列4--开源大模型本地部署到微调(WIP)

背景 一直想真正了解大模型对硬件资源的需求&#xff0c;于是准备详细看一篇视频&#xff0c;将核心要点总结记录下。本文内容参考视频&#xff1a;保姆级教程&#xff1a;6小时掌握开源大模型本地部署到微调&#xff0c;感谢up主 训练成本 训练 > 微调 > 推理训练GPT…

仿《公主连结》首页场景的制作(附资源包)

先看效果&#xff08;主要实现点击按钮切换图片&#xff0c;未解锁按钮弹出提示&#xff0c;点击过后播放动画&#xff09; 预备知识&#xff08;单例模式&#xff0c;携程&#xff0c; Resources.Load加载资源的方式&#xff09; 资源准备&#xff08;底部按钮7个图标&#x…

Redis - 集合 Set 及代码实战

Set 类型 定义&#xff1a;类似 Java 中的 HashSet 类&#xff0c;key 是 set 的名字&#xff0c;value 是集合中的值特点 无序元素唯一查找速度快支持交集、并集、补集功能 常见命令 命令功能SADD key member …添加元素SREM key member …删除元素SCARD key获取元素个数SI…

基于Llamaindex的网页内容爬取实战

目的 本文不关注如何解析网页 html 元素和各种 python 爬虫技术&#xff0c;仅作为一种网页数据的预处理手段进行研究。Llamaindex 也并不是爬虫技术的集大成者&#xff0c;使用它是为了后续的存查一体化。 安装依赖 pip install llama-index-readers-web # pip install llam…

《九重紫》逐集分析鉴赏第一集(下)

主标题&#xff1a;《九重紫》一起追剧吧 副标题&#xff1a;《九重紫》逐集分析鉴赏第一集&#xff08;下&#xff09;/《九重紫》逐集分析鉴赏1 接上回分解&#xff0c;窦昭和宋墨都安置城外万佛寺 交谈没一会儿&#xff0c;天还未亮&#xff0c;兵临寺下 记住这个人&…

Introduction to NoSQL Systems

What is NoSQL NoSQL database are no-tabular非數據表格 database that store data differently than relational tables 其數據的存儲方式與關係型表格不同 Database that provide a mechanism機制 for data storage retrieval 檢索 that is modelled in means other than …

图论【Lecode_HOT100】

文章目录 1.岛屿数量No.2002.腐烂的橘子No.9943.课程表No.2074.实现Trie&#xff08;前缀树&#xff09;No.208 1.岛屿数量No.200 class Solution {public int numIslands(char[][] grid) {if (grid null || grid.length 0) {return 0;}int numIslands 0;int rows grid.len…

【深度学习量化交易9】miniQMT快速上手教程案例集——使用xtQuant获取基本面数据篇

我是Mr.看海&#xff0c;我在尝试用信号处理的知识积累和思考方式做量化交易&#xff0c;应用深度学习和AI实现股票自动交易&#xff0c;目的是实现财务自由~目前我正在开发基于miniQMT的量化交易系统。 在前几篇的文章中讲到&#xff0c;我正在开发的看海量化交易系统&#xf…

网络层IP协议(TCP)

IP协议&#xff1a; 在了解IP协议之前&#xff0c;我们市面上看到的"路由器"其实就是工作在网络层。如下图&#xff1a; 那么网络层中的IP协议究竟是如何发送数据包的呢&#xff1f; IP报头&#xff1a; IP协议的报头是比较复杂的&#xff0c;作为程序猿只需要我们重…

Xcode

info.plist Appearance Light 关闭黑暗模式 Bundle display name 设置app名称&#xff0c;默认为工程名 Location When In Use Usage Description 定位权限一共有3个key 1.Privacy - Location When In Use Usage Description 2.Privacy - Location Always and When In U…

【CSS in Depth 2 精译_079】第 13 章:渐变、阴影与混合模式概述 + 13.1:CSS 渐变效果(一)——使用多个颜色节点

当前内容所在位置&#xff08;可进入专栏查看其他译好的章节内容&#xff09; 第四部分 视觉增强技术 ✔️【第 13 章 渐变、阴影与混合模式】 ✔️ 13.1 渐变 ✔️ 13.1.1 使用多个颜色节点&#xff08;一&#xff09; ✔️13.1.2 颜色插值13.1.3 径向渐变13.1.4 锥形渐变 文…

地下管线三维建模,市面上有哪些软件

1. 地下管线&#xff1a;城市“生命线” 地下管线是城市的重要基础设施&#xff0c;包括供水、排水、燃气、热力、电力、通信等管线&#xff0c;它们如同城市的“生命线”&#xff0c;支撑着城市的正常运转。如果缺乏完整和准确的地下管线信息&#xff0c;施工破坏地下管线的事…

说说你对java lambda表达式的理解?

大家好&#xff0c;我是锋哥。今天分享关于【说说你对java lambda表达式的理解?】面试题。希望对大家有帮助&#xff1b; 说说你对java lambda表达式的理解? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Java Lambda 表达式是 Java 8 引入的一项重要特性&#…

网易云信荣获“HarmonyOS NEXT SDK星河奖”

近日&#xff0c;鸿蒙生态伙伴 SDK 开发者论坛在北京举行。 网易云信凭借在融合通信领域的技术创新和鸿蒙生态贡献&#xff0c;荣获鸿蒙生态“HarmonyOS NEXT SDK星河奖”。 会上&#xff0c;华为鸿蒙正式推出 SDK 生态繁荣伙伴支持计划&#xff0c;旨在为 SDK 领域伙伴和开发…