2024.3.3 训练记录(7)

这几天又忘记每天复习了,以后在实验室复习完再回去好了

最近做1800的题目好多dp啊太ex了

文章目录

  • 牛客 练习赛122D 圆
  • CF 1396B Stoned Game
  • CF 1355C Count Triangles
  • CF 1437C Chef Monocarp
  • CF 271D Good Substrings
  • CF 1475D Cleaning the Phone
  • CF 1362D2 Prefix-Suffix Palindrome (Hard version)
  • CF 722C Destroying Array

牛客 练习赛122D 圆

题目链接

虽然没能自己做出来但是还是挺高兴的,首先是因为用到了之前在atc碰到过然后记录下来的一个trick,就是把圆拉成一条线,弦看作曲线来判断有没有交点,然后也自己想到了转换成求区间最大的思路

剩下没想到的点就是:要记录下来以每个点结束的弦的起始位置,之后更新的时候会用到

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, m;cin >> n >> m;int sum = 0;vector<vector<int>> w(n + 1, vector<int>(n + 1));vector<set<int>> eg(n + 1);for (int i = 0; i < m; i ++ ){int a, b, c;cin >> a >> b >> c;sum += c;w[min(a, b)][max(a, b)] = max(w[min(a, b)][max(a, b)], c);eg[max(a, b)].insert(min(a, b));}vector<vector<int>> dp(n + 1, vector<int>(n + 1));for (int len = 2; len <= n; len ++ ){for (int l = 1; l + len - 1 <= n; l ++ ){int r = l + len - 1;dp[l][r] = max(dp[l][r], dp[l + 1][r - 1]);dp[l][r] = max({dp[l][r], dp[l + 1][r], dp[l][r - 1], dp[l + 1][r - 1] + w[l][r]});for (auto ver : eg[r]){if (ver < l) continue;dp[l][r] = max({dp[l][r], dp[l][ver - 1] + dp[ver][r]});}}}cout << sum - dp[1][n] << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

CF 1396B Stoned Game

题目链接

感觉没有1800 虚高了

优先队列模拟一下,每次取能取的最多的就可以

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n;cin >> n;vector<int> a(n);priority_queue<PII> q;for (int i = 0; i < n; i ++ ){cin >> a[i];q.push({a[i], i});}int idx1 = -1, idx2 = -1;bool flag = true; // true表示T的回合 反之while (q.size()){auto t = q.top();q.pop();if (flag){if (t.second == idx2){if (q.size() == 0){cout << "HL\n";return;}auto tt = q.top();q.pop();q.push(t);idx1 = tt.second;tt.first -- ;if (tt.first != 0) q.push(tt);}else{t.first -- ;idx1 = t.second;if (t.first != 0) q.push(t);}flag = false;}else{if (t.second == idx1){if (q.size() == 0){cout << "T\n";return;}auto tt = q.top();q.pop();q.push(t);idx2 = tt.second;tt.first -- ;if (tt.first != 0) q.push(tt);}else{t.first -- ;idx2 = t.second;if (t.first != 0) q.push(t);}flag = true;}}if (flag) cout << "HL\n";else cout << "T\n";
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t -- ){solve();}
}

CF 1355C Count Triangles

题目链接

组合数学

枚举x+y的值,因为x最小是a,y最小是b,所以x+y最小是a+b,同时z最小是c,所以x+y最小要是c+1,因此x+y的最小值为max(a+b, c+1),最大值是c+b

现在x+y=i,有多少符合条件的z呢?z的最大值是d和 i - d 里小的那个,最小值是c,所以z有min(i - 1, d) - c + 1种情况

再看对于每个y有多少个符合条件的x呢?

y的取值范围是bc之间,所以x的取值范围是[i-c, i-b],同时x还有[a,b]的限制,于是x的取值情况min(i - b, b) - max(i - c, a) + 1

乘法原理

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int a, b, c, d;cin >> a >> b >> c >> d;int ans = 0;for (int i = max(a + b, c + 1); i <= c + b; i ++ ) // 枚举x+y{ans += (min(i - 1, d) - c + 1) * (min(i - b, b) - max(i - c, a) + 1);}cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

CF 1437C Chef Monocarp

题目链接

dp

dp[i][j] 表示第 i 盘菜在第 j 时间拿出来的最小值

转移方程:dp[i][j] = min(dp[i][j - 1], dp[i - 1][j - 1] + abs(t[i] - j))

(dp真的好难想到啊…

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n;cin >> n;vector<int> t(n + 1);for (int i = 1; i <= n; i ++ ) cin >> t[i];sort(t.begin(), t.end());vector<vector<int>> dp(n + 1, vector<int>(2 * n + 1, INF));for (int i = 0; i <= 2 * n; i ++ ) dp[0][i] = 0;for (int i = 1; i <= n; i ++ ){for (int j = 1; j <= n * 2; j ++ ){dp[i][j] = min(dp[i][j - 1], dp[i - 1][j - 1] + abs(t[i] - j));}}int ans = INF;for (int i = 1; i <= n * 2; i ++ ) ans = min(ans, dp[n][i]);cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t -- ){solve();}
}

CF 271D Good Substrings

题目链接

第一次写出来1800的字符串!

一开始想单纯枚举左右端点利用前缀和,再放到set里判断,但是substr的复杂度肯定就爆了

然后想到trie树,枚举每个位置为开头,把从该位置一直到末尾的字符串存进trie树就可以啦,然后在每个符合条件的地方都打上标记,最后dfs一下整个树,记录ans

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 2e6 + 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;int k;
map<char, bool> mp;
int nxt[N][26], cnt;
bool st[N]; // 该结点结尾的字符串是否存在
int num[N];
int ans = 0;
void insert(string s, int l) // 插入字符串,l是字符串长度
{ int p = 0;for (int i = 0; i < l; i++){int c = s[i] - 'a';if (!nxt[p][c]) nxt[p][c] = ++ cnt; // 如果没有,就添加结点if (!mp[s[i]]) num[nxt[p][c]] = num[p] + 1;else num[nxt[p][c]] = num[p];p = nxt[p][c];if (num[p] <= k) st[p] = true;}
}void dfs(int u)
{if (st[u]) ans ++ ;for (int i = 0; i < 26; i ++ ){if (!nxt[u][i]) continue;dfs(nxt[u][i]);}
}void solve()
{string s;cin >> s;for (int i = 0; i < 26; i ++ ){char c;cin >> c;if (c == '1') mp[(char)(i + 'a')] = true;else mp[(char)(i + 'a')] = false;}cin >> k;for (int i = 0; i < s.size(); i ++ ){string ns = s.substr(i, s.size() - i);insert(ns, s.size() - i);}dfs(0);cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

CF 1475D Cleaning the Phone

题目链接

因为看到b只可能为1/2,所以肯定是有啥特殊的地方

于是想到把b为1和2的分开算,每次枚举在b为1的集合中取了几个(肯定是从大到小取),二分查找b为2的集合中需要取几个,更新答案就好啦

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 2e6 + 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;void solve()
{int n, m;cin >> n >> m;vector<int> a(n + 1), b(n + 1);for (int i = 1; i <= n; i ++ ) cin >> a[i];for (int i = 1; i <= n; i ++ ) cin >> b[i];vector<int> c1, c2;c1.push_back(0), c2.push_back(0);for (int i = 1; i <= n; i ++ ){if (b[i] == 1) c1.push_back(a[i]);else c2.push_back(a[i]);}sort(c1.begin() + 1, c1.end(), greater<int>());sort(c2.begin() + 1, c2.end(), greater<int>());vector<int> pre1(c1.size()), pre2(c2.size());for (int i = 1; i < c1.size(); i ++ ) pre1[i] = pre1[i - 1] + c1[i];for (int i = 1; i < c2.size(); i ++ ) pre2[i] = pre2[i - 1] + c2[i];int ans = INF;for (int i = 0; i < c1.size(); i ++ ){int save = m - pre1[i];int pos = lower_bound(pre2.begin(), pre2.end(), save) - pre2.begin();if (pos == c2.size()) continue;ans = min(ans, pos * 2 + i);}if (ans == INF) ans = -1;cout << ans << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t -- ){solve();}
}

CF 1362D2 Prefix-Suffix Palindrome (Hard version)

题目链接

今天学到的新算法:Manacher马拉车算法

这一题只需要先判断原字符串的前缀和后缀有多少对称的,如果完全对称直接输出原字符串,如果还有剩下的不对称,就求剩下的部分中最长前缀/后缀回文子串(哪个长要哪个),套个板子就可以

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 2e6 + 10;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;int flag;string Manacher(string s)
{int sl = s.size(); // 原字符串长度if (sl == 0 || sl == 1) return s;// 构建新串string ns = "$#";for (int i = 0; i < sl; i ++ ){ns += s[i];ns += '#';}int len = ns.size();int c = 0; // 最靠右的回文子串的中心点下标int m = 0; // 最靠右的回文子串的右端点下标int pos = 0; // 最长回文子串的中心点int maxlen = 0; // 最长回文子串的半径(不包括中心点)(新字符串中)vector<int> p(len); // p[i]表示以i为中心点的回文子串的半径(包括i)for (int i = 1; i < len; i ++ ){if (i < m) p[i] = min(p[c - (i - c)], m - i + 1); // c-(i-c)是i关于c的对称点 当前情况表示i在目前最靠右侧的回文子串中else p[i] = 1 + (ns[i] != '#'); // 当前不是#的话 其两侧就是# 所以半径可以加1if (i - p[i] >= 0 && i + p[i] < ns.size())while (ns[i - p[i]] == ns[i + p[i]]) p[i] ++ ; // 对半成品的i位置进行中心扩散if (i + p[i] - 1 > m) // 产生了比以c为中心时更靠右的回文子串{c = i;m = i + p[i] - 1;}if (p[i] == i && maxlen < p[i]){maxlen = p[i] - 1;pos = i;// flag = 1;}if (p[i] + i == len && maxlen < p[i]){maxlen = p[i] - 1;pos = i;// flag = 2;}}string ans = "";char tmp;for (int i = 0; i < 2 * maxlen * 1; i ++ ) // 遍历最长字串的每个位置 得出原字符串中的最长字串{tmp = ns[pos - (maxlen - 1) + i];if (tmp != '#') ans += tmp;}return ans;
}void solve()
{string s;cin >> s;int idx1 = 0, idx2 = s.size() - 1;while (idx1 < idx2){if (s[idx1] != s[idx2]) break;idx1 ++ , idx2 -- ;}if (s[idx1] != s[idx2]){string ss = s.substr(idx1, idx2 - idx1 + 1);string ans = Manacher(ss);string tmp1 = s.substr(0, idx1), tmp2 = s.substr(idx2 + 1, s.size() - idx2 - 1);ans = tmp1 + ans + tmp2;cout << ans << '\n';}else cout << s << '\n';
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;cin >> t;while (t -- ){solve();}
}

CF 722C Destroying Array

题目链接

没脑子了,用线段树写的,写完一搜题解原来是并查集

#include <bits/stdc++.h>using namespace std;#define int long long
using i64 = long long;typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;const int N = 100010;
const int mod = 998244353;
const int maxn = 1e6 + 10;
const int mod1 = 954169327;
const int mod2 = 906097321;
const int INF = 0x3f3f3f3f3f3f3f3f;int a[N];struct Node
{int l, r;int maxx, maxl, maxr, sum;
} tr[N * 4];void pushup(Node& u, Node& l, Node& r)
{u.l = l.l, u.r = r.r;u.maxl = l.maxl;if (l.maxl == l.sum && r.maxl > 0) u.maxl += r.maxl;u.maxl = max(-INF, u.maxl);u.maxr = r.maxr;if (r.sum == r.maxr && l.maxr > 0) u.maxr += l.maxr;u.maxr = max(-INF, u.maxr);u.maxx = max({l.maxx, r.maxx, l.maxr + r.maxl, -INF});u.sum = l.sum + r.sum;
}void pushup(int u)
{pushup(tr[u], tr[u << 1], tr[u << 1 | 1]);
}void build(int u, int l, int r)
{tr[u] = {l, r};if (l == r){tr[u].maxx = tr[u].maxl = tr[u].maxr = tr[u].sum = a[l];return;}int mid = l + r >> 1;build(u << 1, l, mid);build(u << 1 | 1, mid + 1, r);pushup(u);
}void modify(int u, int pos, int x)
{if (tr[u].l == pos && tr[u].r == pos){tr[u].maxx = tr[u].maxl = tr[u].maxr = x;return;}int mid = tr[u].l + tr[u].r >> 1;if (pos <= mid) modify(u << 1, pos, x);else modify(u << 1 | 1, pos, x);pushup(u);
}void solve()
{int n;cin >> n;for (int i = 1; i <= n; i ++ ) cin >> a[i];build(1, 1, n);for (int i = 0; i < n; i ++ ){int pos;cin >> pos;modify(1, pos, -INF);cout << max((i64)0, tr[1].maxx) << '\n';}
}signed main()
{ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int t = 1;// cin >> t;while (t -- ){solve();}
}

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

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

相关文章

“羊驼“入侵CV,美团浙大沈春华团队将LLaMA向CV扩展,构建全新基础模型VisionLLaMA

本文首发:AIWalker https://arxiv.org/abs/2403.00522 https://github.com/Meituan-AutoML/VisionLLaMA 本文概述 大型语言模型构建在基于Transformer的架构之上来处理文本输入, LLaMA 系列模型在众多开源实现中脱颖而出。类似LLaMa的Transformer可以用来处理2D图像吗&#xf…

Python绘制不同形状词云图

目录 1.基本词云图1.1 导入所需库1.2 准备词汇1.3 配置参数并生成词云图1.4 在Python窗口中显示图片1.5 效果展示1.6 完整代码 2. 不同形状词云图2.1 找到自己所需形状图片2.2 利用PS将图片设置为黑白色2.3 在代码中设置背景2.4 效果展示 1.基本词云图 1.1 导入所需库 import…

远程调用--webClient

远程调用webClient 前言1、创建webClient2、准备数据3、执行请求4、接收返回响应到的数据整体代码 前言 非阻塞、响应式HTTP客户端 1、创建webClient WebClient client WebClient.create();2、准备数据 Map<String,String> params new HashMap<>();params.pu…

贪心算法(区间问题)

452. 用最少数量的箭引爆气球 题目(求无重复区间) 有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points &#xff0c;其中points[i] [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。 一支弓箭可以沿着…

利用Python爬取8684公交路线查询网站中全国公交站点信息

利用python语言结合requests、BeautifulSoup等类库爬取https://api.8684.cn/v3/api.php?docitys&actprovince对应接口中所有城市公交路线信息以及公交站点信息。 import time import requests import json, re from bs4 import BeautifulSoup# 定义一个函数&#xff0c;传…

“祖传代码“的是是非非

程序员眼中的“祖传代码”&#xff0c;就像一本古老而神秘的魔法书&#xff0c;藏着无穷的智慧和技巧&#xff0c;有些代码像家传宝贝&#xff0c;有些像祖传秘方。快来分享一下你遇到的“祖传代码”吧~ 祖传代码的历史与文化价值 祖传代码通常指的是经过长时间使用和传承的代…

【DUSt3R】2张图2秒钟3D重建

【DUSt3R】2张图2秒钟3D重建 1. DUSt3R是一种用于稠密和无约束立体三维重建的方法,其实现步骤如下:2. 实际运行效果3. 运行结果4. 自问自答4.1 为社么这里要是使用transform模型呢?4.2 CroCo(通过跨视图完成3D视觉任务的自我监督预训练的一个研究)在DUSt3R的作用是什么,为…

打家劫舍(java版)

&#x1f4d1;前言 本文主要是【动态规划】——打家劫舍(java版)的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是听风与他&#x1f947; ☁️博客首页&#xff1a;CSDN主页听风与他 &#x1f304;每日一…

17 easy 290. 单词规律

//给定一种规律 pattern 和一个字符串 s &#xff0c;判断 s 是否遵循相同的规律。 // // 这里的 遵循 指完全匹配&#xff0c;例如&#xff0c; pattern 里的每个字母和字符串 s 中的每个非空单词之间存在着双向连接的对应规律。 // // // // 示例1: // // //输入: patte…

24计算机考研调剂 | 西安工大

西安工大 考研调剂招生信息 学校:西安工大 专业:- 年级:2024 招生人数:4 招生状态:正在招生中 联系方式:********* (为保护个人隐私,联系方式仅限APP查看) 补充内容 欢迎化工、材料、环工等专业[或有计算机相关专业&#xff08;智能科学和软件工程方向&#xff09;、机…

一款不错的多端SSH工具:Xterminal

1、不仅是强大的SSH工具&#xff0c;更提供本地控制台&#xff0c;以及更多即将推出的开发相关功能&#xff0c;让您专注于创造卓越的代码 2、AI赋能&#xff0c;智能命令提示&#xff0c;为大脑解压 AI解答&#xff0c;让你的疑问得到即时解答 AI智能提示&#xff0c;让每一…

CodeFlying 和 aixcoder两大免费软开平台,孰强孰弱?

今天为大家带来码上飞CodeFlying和aixcoder两款免费的软件开发平台效果的测评 一、产品介绍 首先简单介绍一下这两个平台 码上飞CodeFlying&#xff1a;码上飞 CodeFlying | AI 智能软件开发平台&#xff01; 是一款革命性的软件开发平台&#xff0c;它通过将软件工程和大模…

Redis是AP的还是CP的?

redis是一个开源的内存数据库&#xff0c;那么他到底是AP的还是CP的呢&#xff1f; 有人说&#xff1a;单机的是redis是cp的&#xff0c;而集群的redis是ap的&#xff1f; 但是我不这么认为&#xff0c;我觉得redis就是ap的&#xff0c;虽然在单机redis中&#xff0c;因为只有…

Git 基本操作 ⼯作区、暂存区、版本库

创建本地仓库&#xff1a; 创建 Git 本地仓库 要提前说的是&#xff0c;仓库是进行版本控制的⼀个文件目录。我们要想对文件进行版本控制&#xff0c;就必须先创建⼀个仓库出来。 首先touch 一个文件&#xff1a; 初始化仓库&#xff1a; 创建完成后&#xff0c;我们会发现当前…

行列式错题本

《1800》 1 阶数和转置 A是三阶,B是4阶,还有2这个系数 2 怎么啥也不会呀,委屈 行列式的拆分+提取系数 3

uniapp 安装安卓、IOS模拟器并调试

一、安装Android模拟器并调试 1.下载并安装Android Studio。 2.创建简单project。 3.安装模拟器。 完成安卓模拟器的安装。 4.启动模拟器。 5.hbuilderx选择模拟器、运行。 点击刷新按钮后出现模拟器&#xff0c;勾选并运行。 6.调试。 在 HBuilderX 中&#xff0c;项目启…

每天一道leetcode:20.有效的括号(简单;栈的经典题目)

⭐今日份题目 给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; 左括号必须用相同类型的右括号闭合。 左括号必须以正确的顺序闭合。 每个右括号都有一个对…

Nano 33 BLE Sense Rev2学习第一节——环境配置

参考文档见Access Barometric Pressure Sensor Data on Nano 33 BLE Sense | Arduino Documentation 打开Arduino ide安装开发板 选择开发板 连接开发板到电脑&#xff0c;自动识别开发板端口&#xff0c;选择端口

Python-类型检查:typing模块和mypy工具

Python-类型检查&#xff1a;typing模块和mypy工具 >>返回Python系列文章目录<< 文章链接: Python中typing模块 文章链接: PyCharm集成类型检查mypy

ssh 一次执行多条命令(后台运行)

文章目录 1. 背景2. 命令2.1 命令分隔符2.2 多行脚本2.3 单行脚本 3. SSH 任务后台运行 1. 背景 有时我们只需要远程执行一次任务然后就关闭&#xff0c;而不需要长时间 ssh 登录到远程服务器。同时一次任务可能需要执行多条命令&#xff0c;那么我们该如何做呢&#xff1f; …