Atcoder Beginner Contest 385(补题)
Atcoder Beginner Contest 385
C - Illuminate Buildings(DP)
问题陈述
有
你想给其中一些建筑物装上灯饰,以满足以下两个条件:
- 所选建筑物的高度相同。
- 所选建筑物的排列间隔相等。
您最多可以选择多少座建筑物?如果您选择的建筑物只有一幢,则认为它满足条件。
输入
输入内容由标准输入法提供,格式如下
输出
打印答案。
思路
一般最优性问题都可以考虑一下dp是否可做,这道题刚好是dp。
状态定义:
表示以 i
栋建筑物结尾,间隔为j
的,最多可以选择的建筑物数量.
状态转移:
f(i, j) = max(f(i, j), f(i-1, j) + 1) (1 <= j <= i) H(i) = H(i-j)
初始条件:
f(i, j)初始值都为1
评述
思考方向有误,明明想了一下dp但是有去找其他方法。代码不是自己写的,找到题解,懒得写。
代码
#include <bits/stdc++.h> using namespace std; int main() { int N; cin >> N; std::vector<int> H(N); for (int i = 0; i < N; i ++) cin >> H[i]; std::vector<vector<int>> dp(N, vector<int>(N + 1)); for (int i = 0; i < N; i ++) { for (int j = 1; j <= N; j ++) dp[i][j] = 1; for (int j = 1; j <= i; j ++) if (H[i - j] == H[i]) dp[i][j] = max(dp[i][j], dp[i - j][j] + 1); } int res = 0; for (int i = 0; i < N; i ++) res = max(res, *max_element(dp[i].begin(), dp[i].end())); cout << res << endl; }
Santa Claus 2(差分+二分+优化)
问题陈述
在二维平面上的点
最初,圣诞老人位于点
- 对于
的顺序,他的移动如下:- 假设
是他目前所在的点。- 如果
是 "U",则从 直线移动到 。 - 如果
是 "D",则从 直线移动到 。 - 如果
是 "L",则从 直线移动到 。 - 如果
为 "R",则从 沿直线移动到 。
- 如果
- 假设
找出他完成所有行动后所在的点,以及他在行动过程中经过或到达的不同房子的数量。如果多次经过同一房屋,则只计算一次。
限制因素
- 成对的
是不同的。 没有房子。- 每个
都是 "U"、"D"、"L"、"R "中的一个。 - 所有输入的数字都是整数。
Input
The input is given from Standard Input in the following format:
输出
设
思路
题目本身的逻辑不难,但是写起来比较麻烦,而且非常考查优化能力。
我们只需要维护出每一条纵轴和每一条横轴上点的信息和线段的信息,然后统计答案即可
以纵轴为例,枚举每一条纵轴,将这条纵轴上的点排序,在枚举这条纵轴上的线段,用二分查找的方式找到在线段上的点的范围,用差分的方式记录,最后求前缀和得到在线段上的点。枚举横轴时同理。
最后统计答案即可。
评述
麻烦麻烦麻烦麻烦
#include <bits/stdc++.h> #define int long long using namespace std; signed main() { int N, M, Sx, Sy; cin >> N >> M >> Sx >> Sy; std::vector<int> X(N), Y(N); // SX(i):在i这条纵轴上点的集合 // SY(i):在i这条横轴上点的集合 map<int, vector<pair<int, int>>> SX, SY; for (int i = 0; i < N; i ++) { cin >> X[i] >> Y[i]; SX[X[i]].push_back({Y[i], i}); SY[Y[i]].push_back({X[i], i}); } // x(i):在i这条纵轴上的线段集合 // y(i):在i这条横轴上的线段集合 map<int, vector<pair<int, int>>> x, y; for (int i = 0; i < M; i ++) { char op; int d; cin >> op >> d; if (op == 'L') { Sx -= d; y[Sy].push_back({Sx, Sx + d}); } else if (op == 'R') { Sx += d; y[Sy].push_back({Sx - d, Sx}); } else if (op == 'U') { Sy += d; x[Sx].push_back({Sy - d, Sy}); } else { Sy -= d; x[Sx].push_back({Sy, Sy + d}); } } //标记每一个房子是否满足题意 std::vector<int> res(N); //考查每一条纵轴 for (auto i : x) { // i.first:表示第i条纵轴,i.second:表示第i条纵轴上的线段集合 sort(SX[i.first].begin(), SX[i.first].end()); std::vector<int> ok(SX[i.first].size() + 1); for (auto j : i.second) { //j:表示第i.first条纵轴上的每一条线段 // 用二分的方式查找哪些点在j这条线段上 int L = lower_bound(SX[i.first].begin(), SX[i.first].end(), make_pair(j.first, 0ll)) - SX[i.first].begin(); int R = upper_bound(SX[i.first].begin(), SX[i.first].end(), make_pair(j.second, (long long)1E18)) - SX[i.first].begin() - 1; ok[L] ++, ok[R + 1] --; } for (int j = 1; j < SX[i.first].size(); j ++) ok[j] += ok[j - 1]; for (int j = 0; j < SX[i.first].size(); j ++) if (ok[j]) res[SX[i.first][j].second] = 1; } //考查每一条横轴 for (auto i : y) { sort(SY[i.first].begin(), SY[i.first].end()); std::vector<int> ok(SY[i.first].size() + 1); for (auto j : i.second) { int L = lower_bound(SY[i.first].begin(), SY[i.first].end(), make_pair(j.first, 0ll)) - SY[i.first].begin(); int R = upper_bound(SY[i.first].begin(), SY[i.first].end(), make_pair(j.second, (long long)1E18)) - SY[i.first].begin() - 1; ok[L] ++, ok[R + 1] --; } for (int j = 1; j < SY[i.first].size(); j ++) ok[j] += ok[j - 1]; for (int j = 0; j < SY[i.first].size(); j ++) if (ok[j]) res[SY[i.first][j].second] = 1; } cout << Sx << ' ' << Sy << ' ' << accumulate(res.begin(), res.end(), 0) << endl; }
本文作者:califeee
本文链接:https://www.cnblogs.com/califeee/p/18623500
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效