leetcode第 381 场周赛最后一题 差分,对称的处理

这篇具有很好参考价值的文章主要介绍了leetcode第 381 场周赛最后一题 差分,对称的处理。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

第 381 场周赛 - 力扣(LeetCode)最后一题3017. 按距离统计房屋对数目 II - 力扣(LeetCode)

dijkstra超时了,看了灵神的解题方法力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台,其实是差分优化的暴力统计

灵神说的“撤销操作”,就是先不加那条xy新路,统计出所有距离对数,然后再加上那条路做修改。做修改需要推一下变短的位置。

灵神封装写的特别好,这道题不封装一下,有问题改起来很麻烦。

目录

统计原始距离对数:

找规律:

灵神暴力左右:

差分:

做修改:

第一种:

第二种:

关于小于区间右端点(x+y)/2:(等于过不了)

当 x==y 及x == y+1时没有缩短任何距离。不需要操作

参考代码:


统计原始距离对数:

这里说两种方法,第一种是自己想的找规律(其实踩坑了,没弄好差分),第二种就是灵神暴力,时间复杂度是相同的O(n)

找规律:

分别对奇数和偶数找一下:

第一行1 2 3 4 5五个数是题目里的房屋,左边第一列是距离 t,表中的则是与这个房屋距离为t的房屋数。

我们暴力完成这个表。

比如第一行,对1来说距离为1的只有2一个,所以是1;对2来说距离为1的是1和3,即两个。

会发现每一行会比前一行少2,而第一行也是“1 2 2 .. 2 2 1”可以列式算出来,所以可以距离为1到n的房屋对数数组(我们要返回的数组)给初始化。

        //      1 2 3 4 5
        //1:    1 2 2 2 1   //2就算最多啦
        //2:    1 1 2 1 1   //-2
        //3:    1 1 0 1 1   //-2
        //4:    1 0 0 0 1   //-2
        //5:    0 0 0 0 0   //-2 这个要减成0

        //      1 2 3 4 5 6
        //1:    1 2 2 2 2 1
        //2:    1 1 2 2 1 1     //-2
        //3:    1 1 1 1 1 1     //-2
        //4:    1 1 0 0 1 1     //-2
        //5:    1 0 0 0 0 1     //-2
        //6:    0 0 0 0 0 0     //-2

注意:

房屋数为n的情况下,不存在距离为n的房屋对(最大也是1和n之间差n-1),所以返回数组最后一位必定是0.

灵神暴力左右:

对于房屋 i ,距离为1的就是 i-1 和 i+1 ,距离为2的就是 i-2 和 i+2 ,......

一直到两边,可得左侧距离最大为i-1,右侧为n-i,

所以距离为 1 ~ i -1  的都要加一对,距离为 1 ~ n - i 的也都要加一对

差分:

而我们正好用的是差分数组。差分就是第一位为初始值,后面的都表示和前一位相差的值。对这种连续的情况,用差分是秒算的。

做修改:

首先看情况,其实就四种会变短,而这四种是对称的,也就是说其实就两种情况。

我们 i 为始点,j为终点,(x,y)为新增的路,我们让x<y。

第一种:

i 在 x左边    i <= x 

只有当 j 在y左右的时候才会缩短距离:

leetcode第 381 场周赛最后一题 差分,对称的处理,力扣周赛,leetcode,算法,差分,对称

j在y左的位置的计算:就是算什么时候走新路更短

 leetcode第 381 场周赛最后一题 差分,对称的处理,力扣周赛,leetcode,算法,差分,对称

偶数的话会有一个点,这个点不走(大于号嘛,不取)

奇数的话本是两点之间,正好向下取整了,如下图的a,中间是正好,所以b可取

leetcode第 381 场周赛最后一题 差分,对称的处理,力扣周赛,leetcode,算法,差分,对称

第二种:

x < i < (x+y)/2      剩下的区间就是对称的

leetcode第 381 场周赛最后一题 差分,对称的处理,力扣周赛,leetcode,算法,差分,对称

第二种的y左这个j的计算

leetcode第 381 场周赛最后一题 差分,对称的处理,力扣周赛,leetcode,算法,差分,对称

关于小于区间右端点(x+y)/2:(等于过不了)

这个短点也没有缩短的:

奇数情况        x -  - i - - y       很明显i到x和y一样远

偶数情况        x - i - - y          i直接到y为3,i到x再到y为2+1 == 3

所以<(x+y)/2

——————

当 x==y 及x == y+1时没有缩短任何距离。不需要操作

参考代码:

灵神那个写的好,我没封装。不过对称的处理可以看看,处理是类似的。

他用函数会还原,我是用个if 还原的,然而if条件有关于对称用的值的,所以后面可能进不去,还原失败。文章来源地址https://www.toymoban.com/news/detail-817130.html

class Solution {
#define ll long long
    vector<ll>ans;
    void add(int l, int r, int v)
    {
        if(l>r)return;
        ans[l] += v;
        ans[r + 1] -= v;
    }
public:
    vector<long long> countOfPairs(int n, int x, int y)
    {
        if (x>y)swap(x, y);

        ans = vector<ll>(n + 2);
        // ans[1] = n + n - 2;
        // for (int i = 2; i <= n - 1; i++)
        // {
        //     ans[i] = -2;
        // }
        //

            for (int k = 1; k <= n; k++)
            {
                int i = k,orx = x,ory = y;
                add(1, i - 1, 1);
                add(1, n - i, 1);
                if (y - x < 2)continue;
                if (k > (orx + ory + 1) / 2)
                {
                    i = n + 1 - k;
                    x = n + 1 - ory;
                    y = n + 1 - orx;
                }
                if (i <= x)
                {
                    //1.j>=y
                    add(y - i, n - i,-1);
                    
                    //add(x-i+1,x-i+1+n-y, 1);没有想用“缩短的距离”
                    int dec = y - x - 1;//比如 2 3 连完还是1,缩短了0,3-2-1
                    add(y - i - dec, n - i - dec, 1);

                    //2.x<j<y       i    x     j y
                    //只管能短的,即:j-i > x-i + 1 + y-j
                    //              2j > x+y+1
                    //               j > (x+y+1)/2
                    //j==(x+y+1)/2+1
                    int j = (x + y + 1) / 2 + 1;
                    //j到y-1
                    add(j-i,y-i-1,-1);

                    add(x - i + 2, x-i + 1 + y-j, 1);
                    //3.j<=x不用管
                }
                else if (i < (x + y) / 2)// x - i - y 与 x - i - - y 都是不起作用,不需等于
                {                        //等于的话
                    //y右:
                    add(y-i,n-i,-1);
                    int dec = y - i - (i - x + 1);
                    add(y - i-dec, n - i-dec, 1);

                    //y左:
                    //j-i>i-x+1+y-j
                    //2j>2i-x+1+y
                    //j>(2i-x+1+y)/2
                    int j = i + (- x + 1+ y) / 2 + 1;
                    add(j-i,y-1-i,-1);
                    add(i - x +2, i - x + y - j + 1,1);
                }

                if (k > (orx + ory + 1) / 2)
                {
                    x = orx;
                    y = ory;
                }
            }
        vector<ll>ret(n);
        ll sum_d = 0;
        for (int i = 0; i < n; i++)
        {
            sum_d += ans[i+1];
            ret[i] = sum_d;
        }
        return ret;
    }
};

到了这里,关于leetcode第 381 场周赛最后一题 差分,对称的处理的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [LeetCode周赛复盘] 第 348场周赛20230604

    这场可惜了。 T1 模拟。 T2 模拟。 T3 倒序计算。 T4 同时限制上下界的数位DP。 6462. 最小化字符串长度 1. 题目描述 2. 思路分析 题意仔细想一下就会发现,其实会将每个字符仅留1个。 3. 代码实现 6424. 半有序排列 1. 题目描述 2. 思路分析 由于只能相邻交换来移动,因此每次只能

    2024年02月08日
    浏览(37)
  • [LeetCode周赛复盘] 第 359 场周赛20230820

    T1 模拟。 T2 数学贪心。 T3 dp。 T4 分组+滑窗。 2828. 判别首字母缩略词 1. 题目描述 2. 思路分析 按题意模拟即可。 3. 代码实现 2829. k-avoiding 数组的最小总和 1. 题目描述 2. 思路分析 贪心 1~k-1中,选了1就不能选k-1;选了2就不能选k-2… 因此可以选1~k//2 剩余的从k开始向上选。 可以

    2024年02月11日
    浏览(33)
  • leetcode 第360场周赛

    好久没参加leetcode周赛了,比赛时间都从两小时变成了一个半小时。这次周赛由两道签到题和两道中等难度题组成,严格来说最后一道的难度也可以视为hard,但是只要想到正确的思路,编码还是比较容易的。 比赛链接:leetcode 第 360 场周赛 题目描述 给你一个长度为 n 的字符串

    2024年02月11日
    浏览(36)
  • LeetCode第354场周赛

    给你一个下标从 1 开始、长度为 n 的整数数组 nums 。 对 nums 中的元素 nums[i] 而言,如果 n 能够被 i 整除,即 n % i == 0 ,则认为 num[i] 是一个 特殊元素 。 返回 nums 中所有 特殊元素 的 平方和 。 直接模拟就好了 给你一个下标从 0 开始的整数数组 nums 和一个 非负 整数 k 。 在一

    2024年02月16日
    浏览(53)
  • LeetCode第343场周赛

    2023.4.30LeetCode第343场周赛 根据题意模拟 使用哈希表记录每个数出现的位置,再用m+n个集合记录每一行和每一列被涂满的格子数,若某行或某列全部被涂满则返回答案 BFS 首先将距离大于两点的曼哈顿距离的特殊路径去掉 每个点考虑经过每个特殊路径到达,分成两段,一段是当

    2024年02月02日
    浏览(40)
  • LeetCode第347场周赛

    2023.5.28LeetCode第347场周赛 从最后一位开始遍历,为0则跳过 暴力模拟 对于每个 s[i] != s[i - 1] ,要使其相等 有两种选择,翻转前 i 个,或者翻转后 n - i 个,选择代价最小的方案 动态规划 从小到大枚举所有值,每个值一定是从更小的数转移而来 定义动态规划数组f, f[i][j] 表示

    2024年02月06日
    浏览(72)
  • leetcode第 357/358 场周赛

    可能别人有更好的解法,我这写法是不断往线段树中插入数值,每次先插入nums[i-x],然后搜索(1到i)中的最大值和(i到max)中的最小值去更新ans。 看了看别人题解,直接用set写是真的牛。自己还是见识短浅了。 暴力乱搞,考虑两种极端情况,一种无脑选profit大的,一种优先选

    2024年02月12日
    浏览(38)
  • leetcode第354场周赛补题

    6889. 特殊元素平方和 - 力扣(LeetCode) 思路:模拟 6929. 数组的最大美丽值 - 力扣(LeetCode) 思路:排序+双指针 6927. 合法分割的最小下标 - 力扣(LeetCode) 思路:哈希+枚举 6924. 最长合法子字符串的长度 - 力扣(LeetCode) 思路:哈希+双指针

    2024年02月16日
    浏览(35)
  • Leetcode 第 365 场周赛题解

    思路 暴力。 代码 复杂度分析 时间复杂度:O(n 3 ),其中 n 是数组 nums 的长度。 空间复杂度:O(1)。 思路 枚举 k,我们需要知道 k 左边 nums[i]−nums[j] 的最大值。 使用 pre_max 维护 k 之前的 nums[i] 的最大值,使用 max_diff 维护 nums[i]−nums[j] 的最大值。 每次遍历一个 nums[i],都更新

    2024年02月07日
    浏览(32)
  • LeetCode 第385场周赛个人题解

    目录 100212. 统计前后缀下标对 I 原题链接 题目描述 接口描述 思路分析 代码详解 100229. 最长公共前缀的长度 原题链接 题目描述 接口描述 思路分析 代码详解 100217. 出现频率最高的素数 原题链接 题目描述 接口描述 思路分析 代码详解 100212. 统计前后缀下标对 II 原题链接 题目

    2024年02月19日
    浏览(60)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包