1589. 所有排列中的最大和 #差分 #贪心

题目链接

题意

给定整数数组nums,以及查询数组requests,其中requests[i] = [starti, endi] 。第i个查询求 nums[starti] + nums[starti + 1] + ... + nums[endi - 1] + nums[endi] 的结果 。

你可以任意排列 nums 中的数字,请你返回所有查询结果之和的最大值,请将答案对 109 + 7 取余 后返回。

分析

我们先离线获得需要查询的区间,并统计该查询涉及端点的出现次数(也就是频数)。显然由贪心思想,我们要想答案尽可能地大,就应该将值更大的元素安排到出现次数更多的端点上,即高频数\(\times\)大元素。

  1. typedef long long ll;
  2. const int MAXN = 1e5 + 5;
  3. const int MOD = 1e9 + 7;
  4. class Solution {
  5. private:
  6. int cf[MAXN];
  7. vector<int> used;
  8. public:
  9. int maxSumRangeQuery(vector<int>& nums, vector<vector<int>>& requests) {
  10. for (int i = 0; i < requests.size(); i++){
  11. int a = requests[i][0], b = requests[i][1];
  12. cf[a]++;
  13. cf[b + 1]--;
  14. }
  15. int sum = 0;
  16. for (int i = 0; i < nums.size(); i++){
  17. sum += cf[i];
  18. used.push_back(sum);
  19. }
  20. sort(used.begin(), used.end(), greater<int>());
  21. sort(nums.begin(), nums.end(), greater<int>());
  22. ll ans = 0;
  23. for (int i = 0; i < used.size(); i++){
  24. ans += ((ll)used[i] * (ll)nums[i]);
  25. }
  26. return ans % MOD;
  27. }
  28. };

1590. 使数组和能被 P 整除 #前缀和 #哈希表

题目链接

题意

给定正整数数组 nums,请你移除 最短 子数组(即原数组中连续的一组元素,可以为 空),使得剩余元素的 被 p 整除。 不允许 将整个数组都移除。要你返回需要移除的最短子数组的长度,如果无法满足题目要求,返回 -1 。

分析

令\(lastmod = \sum{nums}\ \%\ p\),当\(lastmod==0\)显然无需操作,答案为0;当\(lastmod\not= 0\),我们的问题接下来就变为从原数组中找到一个最短子数组,使得\(\sum{(该子数组)}\% p = lastmod\),此时原数组剩余部分都能被\(p\)整除!

要求一段连续子数组之和,需要前缀和维护。不过注意这个和是经过模\(p\)运算处理的,这样是为了找到一段子数组模\(p\)加法运算得到上一段所说的\(lastmod\)。我们每遍历一个元素,就将其对应的模\(p\)前缀和\(curmod\)在哈希表中映射其对应位置,用于未来查询相应的\(targetMod\)的位置。如下图所示。

如何对当前\(i\)下已知的\(curmod\)求出对应的\(targetMod\)呢?当\(curmod \geq lastmod\)时,之前按下图所示,\(targetMod = curmod - lastmod\);当\(curmod\leq lastmod\)时,就需要加上一个\(p\),即\(targetMod = curmod - lastmod + p\)。上面两种情况合起来就是,\(targetMod = curmod - lastmod + p\)。我们求出\(targetMod\)的值,再通过哈希表查询\(targetMod\)的位置\(pos\),此时长度为\(pos-i\)、区间\([pos, i]\)的子数组,满足其和模\(p\)是等于\(lastmod\)的,更新长度,直到所有元素遍历完,便得到最短长度了。

此处初始化有个重要的小细节,之所以要pos[0] = -1;,是因为在第一次targetMod==0curmod==lastmod时,你从哈希表查询到的位置刚好也是lastmod(刚刚更新的位置),更新的长度就变成0了!!显然它应该更新长度是从[0, lastmod位置]

  1. typedef long long ll;
  2. class Solution {
  3. private:
  4. unordered_map<ll, int> pos; //用于记录总和取了模之后的最新位置,即离当前元素最近的位置,保证题目的“最短”
  5. public:
  6. int minSubarray(vector<int>& nums, int p) {
  7. ll sum = 0;
  8. for(int i = 0; i < nums.size(); i++) sum += (ll)nums[i];
  9. ll lastmod = sum % (ll)p, curmod = 0;
  10. if(lastmod == 0) return 0; //直接返回
  11. if(sum < p) return -1; //和 比 模数更小,显然无法满足题目要求
  12. pos[0] = -1;//一定要先初始化-1!!!
  13. int minlen = 0x3f3f3f3f;
  14. for(int i = 0; i < nums.size(); i++){
  15. curmod = (curmod + nums[i]) % p;
  16. pos[curmod] = i;
  17. ll targetMod = (curmod - lastmod + p) % p;
  18. if(pos.count(targetMod))
  19. minlen = min(minlen, i - pos[targetMod]);
  20. }
  21. return (minlen < nums.size()) ? minlen : -1;
  22. }
  23. };

1591. 奇怪的打印机 II #拓扑排序

题目链接

题意

一个打印机有如下两个特殊的打印规则:

  • 每一次操作时,打印机会用同一种颜色打印一个矩形的形状,每次打印会覆盖矩形对应格子里原本的颜色。
  • 一旦矩形根据上面的规则使用了一种颜色,那么 相同的颜色不能再被使用 。

给定 m x n 的矩形 targetGrid ,其中 targetGrid[row][col] 是位置 (row, col) 的颜色。如果能按上述规则打印出矩形targetGrid,返回 true ,否则返回 false

题目分析

注意到数据范围均在\(60\)以内,意味着我们可以枚举所有的颜色。

  1. class Solution {
  2. private:
  3. int bottom[65], top[65], left[65], right[65];
  4. int InD[65] = { 0 };
  5. vector<int> H[65]; //边集
  6. bool vis[65][65] = { false };
  7. int n, m;
  8. queue<int> myque;
  9. public:
  10. bool isPrintable(vector<vector<int>>& targetGrid) {
  11. n = targetGrid.size(), m = targetGrid[0].size();
  12. for (int i = 1; i <= 60; i++) { //初始化
  13. top[i] = left[i] = 0x3f3f3f3f;
  14. bottom[i] = right[i] = -1;
  15. }
  16. for (int i = 0; i < n; i++) {
  17. for (int j = 0; j < m; j++) {
  18. int curcolor = targetGrid[i][j];
  19. bottom[curcolor] = max(bottom[curcolor], i); //最大下边界
  20. right[curcolor] = max(right[curcolor], j); //以下同理
  21. top[curcolor] = min(top[curcolor], i);
  22. left[curcolor] = min(left[curcolor], j);
  23. }
  24. } //确定所有颜色的上下左右边界
  25. for (int i = 0; i < n; i++) {
  26. for (int j = 0; j < m; j++) {
  27. int curcolor = targetGrid[i][j];
  28. for (int faColor = 1; faColor <= 60; faColor++) {
  29. if (faColor == curcolor || vis[faColor][curcolor]) continue; //重边或者重点,跳过。
  30. if (top[faColor] <= i && i <= bottom[faColor]
  31. && left[faColor] <= j && j <= right[faColor]) { //fa颜色集合包含了curcolor集合
  32. H[faColor].push_back(curcolor); //说明两颜色存在偏序关系
  33. vis[faColor][curcolor] = true;
  34. InD[curcolor]++;
  35. }
  36. }
  37. }
  38. }
  39. /*以下为拓扑排序,通过拓扑排序判断这些偏序关系即有向图,是否存在环,有环说明两颜色集合互相包含*/
  40. int cnt = 0;
  41. for (int i = 1; i <= 60; i++)
  42. if (InD[i] == 0) {
  43. myque.push(i);
  44. cnt++;
  45. }
  46. while (!myque.empty()) {
  47. int u = myque.front();
  48. myque.pop();
  49. for (int i = 0; i < H[u].size(); i++) {
  50. int v = H[u][i];
  51. InD[v]--;
  52. if (InD[v] == 0) {
  53. myque.push(v);
  54. cnt++;
  55. }
  56. }
  57. }
  58. return (cnt == 60);
  59. }
  60. };

LeetCode双周赛#35的更多相关文章

  1. leetcode 双周赛9 进击的骑士

    一个坐标可以从 -infinity 延伸到 +infinity 的 无限大的 棋盘上,你的 骑士 驻扎在坐标为 [0, 0] 的方格里. 骑士的走法和中国象棋中的马相似,走 “日” 字:即先向左(或右 ...

  2. leetcode 双周赛9 找出所有行中最小公共元素

    给你一个矩阵 mat,其中每一行的元素都已经按 递增 顺序排好了.请你帮忙找出在所有这些行中 最小的公共元素. 如果矩阵中没有这样的公共元素,就请返回 -1. 示例: 输入:mat = [[,,,,] ...

  3. [每日一题2020.06.16] leetcode双周赛T3 5423 找两个和为目标值且不重叠的子数组 DP, 前缀和

    题目链接 给你一个整数数组 arr 和一个整数值 target . 请你在 arr 中找 两个互不重叠的子数组 且它们的和都等于 target .可能会有多种方案,请你返回满足要求的两个子数组长度和的 ...

  4. LeetCode双周赛#36

    1604. 警告一小时内使用相同员工卡大于等于三次的人 题目链接 题意 给定两个字符串数组keyName和keyTime,分别表示名字为keytime[i]的人,在某一天内使用员工卡的时间(格式为24 ...

  5. LeetCode双周赛#34

    5492. 分割字符串的方案数 #组合公式 #乘法原理 #区间分割 题目链接 题意 给定01二进制串\(s\),可将\(s\)分割为三个非空 字符串\(s_1,s_2,s_3\),即(\(s_1+s_ ...

  6. LeetCode双周赛#33 题解

    5480. 可以到达所有点的最少点数目 #贪心 题目链接 题意 给定有向无环图,编号从0到n-1,一个边集数组edges(表示从某个顶点到另一顶点的有向边),现要找到最小的顶点集合,使得从这些点出发, ...

  7. Leetcode 双周赛#32 题解

    1540 K次操作转变字符串 #计数 题目链接 题意 给定两字符串\(s\)和\(t\),要求你在\(k\)次操作以内将字符串\(s\)转变为\(t\),其中第\(i\)次操作时,可选择如下操作: 选 ...

  8. LeetCode第8场双周赛(Java)

    这次我只做对一题. 原因是题目返回值类型有误,写的是 String[] ,实际上应该返回 List<String> . 好吧,只能自认倒霉.就当涨涨经验. 5068. 前后拼接 解题思路 ...

  9. LeetCode 第 15 场双周赛

    1287.有序数组中出现次数超过25%的元素 1288.删除被覆盖区间 1286.字母组合迭代器 1289.下降路径最小和 II 下降和不能只保留原数组中最小的两个,hacked. 1287.有序数组 ...

随机推荐

  1. VMware Workstation Pro 虚拟机安装

    1.简介 虚拟机指通过软件莫比的具体有完整硬件系统功能的.运行在一个完全隔离环境中的完整计算机系统. 我们可以通过虚拟机软件,可以在一台物理计算机模拟出一台或多台虚拟的计算机,这些虚拟的计算机完全就像 ...

  2. for循环使用体会

    最近在看源码的时候看到了以下代码: Class[] var2 = componentClasses; int var3 = componentClasses.length; for(int var4 ...

  3. 如何解决 Nginx 端口映射到外网后访问地址端口丢失的问题

    1. 问题说明 一个手机h5页面的项目,使用nginx(监听80端口)进行访问,内网访问的地址是192.168.12.125/h5,访问正常,nginx中的配置如下: #微信H5页面访问 locati ...

  4. 专题四:redis的数据类型之list

    一.基本介绍 对于list,它的存储需求是什么呢?对于string,讲究单个,hash也不讲究大量:当我们需要存储多个数据的时候,前面的数据类型就不大合适了. 数据存储需求:存储多个数据,并对数据进入 ...

  5. Scipy 学习第3篇:数字向量的距离计算

    计算两个数字向量u和v之间的距离函数 1,欧氏距离(Euclidean distance) 在数学中,欧几里得距离或欧几里得度量是欧几里得空间中两点间"普通"(即直线)距离.使用这 ...

  6. 【Android Studio】安卓开发初体验1——安装与试用

    安装 (安装预留硬盘(C盘)空余空间16G以上,8G以上内存) Intel用户: 安装Android Studio和AVD(安卓虚拟机 Android Virtual Device) 安装过程需要注意 ...

  7. springboot data jdbc 数据库日期和查询出来的结果不一致

    解决方法: 一.将serverTimezone=UTC改为CTT url: jdbc:mysql://localhost:3306/moviechoicesystem?serverTimezone=C ...

  8. 老师问学生while判断

    老师问学生,这道题你会做了吗?如果学生答"会了(y)",则可以放学.如果学生不会做(n),则老师再讲一遍,再问学生是否会做了...... (1)直到学生会为止,才可以放学. (2) ...

  9. 重温Java泛型,带你更深入地理解它,更好的使用它!

    1. 引言 jdk5.0中引入了Java泛型,目的是减少错误,并在类型上添加额外的抽象层. 本文将简要介绍Java中的泛型.泛型背后的目标以及如何使用泛型来提高代码的质量. 2. 为什么要用泛型? 设 ...

  10. 有奖体验 CODING 产品,iPad Pro、HHKB 键盘等超级礼包等你来!

    DevOps 研发效能升级.高效率研发工具已成为软件研发行业的热门话题,也是每个企业研发团队需要不断探索的命题.CODING 一站式软件研发管理工具平台旨在让开发团队低门槛使用 DevOps 工具,帮 ...