leetcode 周赛 507

作者: | 更新日期:

TOP N 算法

本文首发于公众号:天空的代码世界,微信号:tiankonguse

零、背景

这次比赛不难,不过由于没睡好,头晕晕的,思路总是断掉,做完四道题时排名比较靠后了。

本场题型概览如下。
A 题:贪心。
B 题:枚举。
C 题:最短路。
D 题:二分+枚举。

一、移动后的最大曼哈顿距离

题意:起初你在坐标原点,告诉你一个上下左右移动的操作顺序数组,某些位置的操作可以任意移动,问最终最大的曼哈顿距离。

思路:贪心

可以发现,任意打乱操作顺序,不影响答案。
故可以先忽略任意操作的位置,把确定的移动先移动了,从而得到一个最大曼哈顿距离。

假设有 K 个任意操作,则在当前最大曼哈顿距离上再加 K 即可。

二、求和后首尾数字相同的有效子数组 I

题意:给你一个数组,问有多少子数组之和的首尾数字都是字符 x。

思路:枚举

双层循环计算所有子数组和,判断首尾数字即可。

三、最多 K 个连续相同字符的最短路径

题意:给你一个有向带权图,每个点有一个标签,求起点到终点的最短路,且路径中不能有连续 k 个相同标签。

思路:Dijkstra

正常的 Dijkstra 是一维的。
这里增加了标签的统计,使用二维 Dijkstra 即可。

// {cost, s, lableCount}
typedef tuple<ll, int, int> tll;  
priority_queue<tll, vector<tll>, greater<tll>> pque;
vector<vector<ll>> dist(n, vector<ll>(k + 1, INF));

while (!pque.empty()) {
  auto [uCost, u, uCount] = pque.top();
  pque.pop();
  if (dist[u][uCount] < uCost) continue;
  for (auto& [v, vCost] : g[u]) {
    Add(u, uCost, uCount, v, vCost);
  }
}

PS:一开始没想好,想成三维的了,考虑到内存可能爆掉,做了各种优化与剪枝,浪费不少时间。

四、最大总价值

题意:有 n 个数字,挑选某个数字后,值就会减少一定的数值。
最多选择 m 个数字,问选择数字的最大和是多少。

思路:二分+枚举

每个数字减少的数值是确定性的,所以是一个递减数列。
m 比较大,不能一个个选择,必须批量选择。

二分出最小的数字,使得大于这个数字的都选择,且满足不大于 m。

ll left = 0, right = maxVal + 1;  // [left, right)
while (left < right) {
  ll mid = (left + right) / 2;
  ll cnt = 0;
  for (auto& [val, dec] : nums) {
    cnt += CalCnt(val, dec, mid);
  }
  if (cnt <= m) {
    right = mid;
  } else {
    left = mid + 1;
  }
}

最后可能会还剩若干个,二分无法选择。
可以确定,这个不会大于 n,优先队列一个个贪心枚举模拟即可。

五、最后

这次比赛比较简单,第三题我想错了浪费了比较多的时间。

《完》

-EOF-

本文公众号:天空的代码世界
个人微信号:tiankonguse
公众号 ID:tiankonguse-code

本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。

关注公众号,接收最新消息

tiankonguse +
穿越