喜欢三叶草的牛

2024-01-20 01:20
文章标签 喜欢 三叶草

本文主要是介绍喜欢三叶草的牛,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2d0d6180c5bdd34c0de8ab99a466fcad.gif

关注下方公众号,分享硬核知识

作者 | 小K

出品 | 公众号:小K算法 (ID:xiaok365)

01

故事起源

山上长满了三叶草,有N只牛,每只牛只喜欢某一个范围的三叶草。

b6416509692139a702de9ed5d72778d8.jpeg

把山看成一个数轴,则每只牛喜欢的三叶草范围可以用一个区间[si,ei]来表示。

ea30541e81cf1345508d8a1eb97835f5.jpeg

如果一只牛i喜欢的范围大于另一只牛j,则认为牛i比牛j更强壮。

1c42121309486eb6da8250b166881e5f.jpeg

也就是满足下面的关系。

e696818dbfb46e681fb071230b2a5086.jpeg

那请问对于每一只牛,有多少只牛比它更强壮呢?

02

分析

题意应该很好理解,其实就是给了很多个区间,求对于每一个区间,它属于多少个区间的真子集。例如下面的红色区间,被两个蓝色区间真包含。

3cbcc5f2009ca16a9d6027fad51d70d2.jpeg

最先想到的肯定是直接遍历。对于每一个区间,遍历剩余的其它区间,O(n^2)搞定。

for (int i=0; i<n; ++i)for (int j=0; j<n; ++j) {if 区间j真包含区间i {ans[i]++}}

最朴实无华的方法,效率肯定不高。那有没有更好的方案呢,这个就得继续找规律了。

03

找规律

先看一下上面最简单的方案有没有什么问题,因为很多优秀的方法都是从最简单的方法一步一步优化出来的。

对于红色区间,我们可以很容易看出,其它区间其实没有遍历的必要,因为都在区间之外,甚至都没有交集。

adc2a6038dd2a180552cd513f47eb4f9.jpeg

这个说明其实跟区间的位置有很强的关系,如果有了相对位置,就可以减少很多计算。

那我们可以考虑一下,是不是能先按照区间排序,比如先按照左端点升序,左端点相同时,右端点降序。

d189c28b04695ab8afe34fee4ed65085.jpeg

再看上面的图中,对于红包区间,可能真包含它的只会在前面的虚线区间中,后面的一定不可能,所以只需要遍历前面的即可。

for (int i=0; i<n; ++i)for (int j=0; j<i; ++j) {if 区间j真包含区间i {ans[i]++}}

这样会减少一些判断,但本质还是O(n^2),还多了一个排序的代价。那有没有可能遍历更少,或者不遍历呢?

再想一下,其实对于红色区间来说,下面所有真包含它的虚线区间,你真的关心它的顺序吗,你只是需要知道它是否包含,即右端点的相对位置。

a2b603f8ba093709d7317037c3ac109c.jpeg

如果先按照左端点升序,那么对于红色区间来说,前面的区间只可以分为两类。一类是右端点在它的右端点左边,另一类是在右边,知道这个数量就够了。

ae71562e68bd11c52fab4667e123f733.jpeg

把所有区间绕左端点竖起来,那么对于红色区间,就变成关注前面区间的上端点是在它的上端点的上面还是下面。

84055c72dfa2dd583beeed28da84a50e.jpeg

再跳出上面的框架来看,我们已经把一个区间[si,ei]投射到了一个二维平面中的点,si,ei即为横纵坐标。再看上面要满足的关系式,其实就是以红色为原点画出四象限,所有左上方第二象限的点都满足。

42526a5de38ff7e06fa8e04499dfaeaa.jpeg

所以一上来根据描述看成是区间反而走了弯路,因为区间也是二维信息,在一维数轴里面无法表示。看成是二维平面就很简单,升维是一种重要的手段,尤其在动态规划中应用非常普遍,一维不行变二维,二维不行三维,四维。。。

现在模型已经建立好了,那下一个问题就是,如何快速求出第二象限的点数量呢?

04

快速统计

把二维中的点投射到y轴上去,压缩成一维,这就变成了求上半块区间中点的数量。因为这个区间需要不断的修改和查询,树状数组是再适合不过了。

e7b7963f18c8b042613d06e6307b7d74.jpeg

05

算法框架

对于所有的点(si,ei),先按照si升序,si相同时按ei降序排列。在y轴上维护一个区间和,依次遍历队列中的点,并将每个点ei坐标所对应在y轴上的位置+1,再统计y轴上的区间上半块的区间和。

aa8f3b21c517a4f0dff3ff3ccb4894e8.jpeg

06

代码实现

fad4023fa1aefdb2394b349355031147.png

6.1

快排

实现一个快排模板,以后就不用再重复敲了。

sort.h

template<typename T>
void sort(T arr[], int start, int end);
#include "sort.inl"
#endif

sort.inl

template<typename T>
void swap(T arr[], int s, int t) {T temp = arr[s];arr[s] = arr[t];arr[t] = temp;
}
template<typename T>
int partition(T arr[], int left, int right) {srand(time(0));int pivot = left + rand() % (right - left + 1);swap(arr, left, pivot);T base = arr[left];while (left < right) {while (left < right && base <= arr[right]) right--;arr[left] = arr[right];while (left < right && arr[left] <= base) left++;arr[right] = arr[left];}arr[left] = base;return left;
}
template<typename T>
void sort(T arr[], int start, int end) {if (start >= end) {return;}int index = partition(arr, start, end);sort(arr, start, index - 1);sort(arr, index + 1, end);
}

8c10b00d234761db4450aa6cdd354457.png

6.2

树状数组

int lowbit(int x) {return x & -x;
}
void add(int sum[], int index, int x) {while (index <= MAX_NUM) {sum[index] += x;index += lowbit(index);}
}
int query(const int sum[], int index) {int ret = 0;while (index > 0) {ret += sum[index];index -= lowbit(index);}return ret;
}

a6018eedf48b845ce4456345c5fea421.png

6.3

定义

#include "sort.h"
#define MAX_NUM 100001
struct Point {int index, x, y;bool operator<=(const Point &node) const {if (x == node.x) {return y >= node.y;}return x < node.x;}
};

bd9305ec53993ceda0a9b792e04c2cca.png

6.4

main

int main() {freopen("../a.in", "r", stdin);freopen("../a.out", "w", stdout);int n;scanf("%d", &n);while (n > 0) {Point cow[MAX_NUM];for (int i = 0; i < n; ++i) {scanf("%d%d", &cow[i].x, &cow[i].y);cow[i].y++;cow[i].index = i;}sort(cow, 0, n - 1);int sum[MAX_NUM] = {0}, ans[MAX_NUM] = {0};for (int i = 0; i < n; ++i) {if (i > 0 && cow[i].x == cow[i - 1].x && cow[i].y == cow[i - 1].y) {ans[cow[i].index] = ans[cow[i - 1].index];} else {ans[cow[i].index] = i - query(sum, cow[i].y - 1);}add(sum, cow[i].y, 1);}for (int i = 0; i < n - 1; ++i) {printf("%d ", ans[i]);}printf("%d\n", ans[n - 1]);scanf("%d", &n);}return 0;
}

07

总结

算法的组合应用是比较难掌握的,建模的过程很难想到,只有真正理解了核心思想,应用起来才能得心应手,多思考,没有捷径。

本文原创作者:小K,一个思维独特的写手。
文章首发平台:微信公众号【小K算法】。

如果喜欢小K的文章,请点个关注,分享给更多的人,小K将持续更新,谢谢啦!

7fc7ccbdfd7a9f9c61c16ff8e8d4f8f6.gif

关注下方公众号,分享硬核知识

9ab0f40537536b28a7435211344ff9c5.gif

关注我,涨知识

6eee6009b4f10faf149a4aa7e8fe1888.gif

原创不易,感谢分享

转发,点赞,在看

往期精彩回顾

原来树状数组可以这么简单?

经典面试题:如何快速求解根号2?

很幸运,我还有工作

e7e45a9c7fe64090f94d00c841fa8d1d.gif

分享给更多朋友,转发,点赞,在看

这篇关于喜欢三叶草的牛的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/624336

相关文章

为什么你不喜欢看书?

哈咯,朋友们!今天我们来聊一聊我自己是怎么从一个不喜欢读书看书的人一步一步的到热爱的,以至于到现在就像中了毒,每天不看书不读书就不舒服。我看书不拘于书的内容,什么书都看点,有的也看一点不愿意看了,有的时候看到某本书某句话想起某本书也会再拿出来翻蹬翻蹬。大数据分析来看,看的比较多的类目还是企业经营管理,职场以及心理学的书。使用京东读书APP看书给我贴的性格十大标签是:人文主义,企业高管,事业心重,I

这才是老板喜欢的产品经理简历

速创猫今天给大家分享的是应届毕业生产品经理简历优化案例,希望对大家求职有帮助。速创猫总结了以下七条简历制作干货,希望对大家有帮助: 明确目标岗位:在简历的开头,明确指出你申请的职位,让招聘者一眼就能看出你的求职意向。 突出核心技能:列出与产品经理职位相关的技能,如需求分析、用户研究、数据分析等,并用实例说明你是如何运用这些技能的。 量化成果:用数字来展示你的成就,比如“提升产品用户满意度

这才是老板喜欢的运营简历

速创猫今天给大家分享的是应届毕业生运营简历优化案例,希望对大家求职有帮助。速创猫总结了以下七条简历制作干货,希望对大家有帮助: 突出实习经验:如果你是应届毕业生,那么实习经验是你的亮点。确保将实习经历放在显眼位置,并详细描述你在实习期间的职责和成就。 量化成果:不要只说“负责社交媒体运营”,而是要具体说明“通过优化内容策略,使粉丝增长了20%”。 技能与职位匹配:仔细阅读招聘广告,找出所

过去的经验4_一些喜欢的博客

发现第一个已经被加密了。哭泣哭泣 一会把其他的都给转载一下,不然以后都不知道是什么了 http://blog.sina.com.cn/s/blog_4bb52a1601012x8j.html  //java调用dll例子。 http://favccxx.blog.51cto.com/2890523/1331115/        //word和excel导入导出 http://blog.c

你喜欢挑毛病吗?

锻炼拥有一种思维比较难,但是避开某种现有的思维方式,是相对容易的。   因为现有思维方式出现的时候,我们稍微锻炼一下就能意识到,但是脑海中没有这种思维方式,那就需要长时间的刻意练习才能养成习惯。   今天要说的思维方式,如果你有,那要注意了,这是一个超级深坑,一定要避开,我自己曾经就经常用这种思维方式和人沟通做事,非常蠢。   所以这个思维方式是什么?也不卖关子了,就是看待复杂事物时,喜欢挑毛病

保存json时,保存成自己喜欢的格式的方法(而不是直接保存成格式化的json文档)

保存json时,不是直接保存成格式化的json文档的格式的方法 前言,博主是如何把格式话的json格式保存成自己喜欢的json格式的保存成格式化的json文档的格式:带缩进格式全部保存成一行每条数据保存成一行: 保存成自己喜欢的格式碎碎念 前言,博主是如何把格式话的json格式保存成自己喜欢的json格式的 保存成格式化的json文档的格式: 带缩进格式 with open(

为什么程序员面试官总喜欢问你有什么技术亮点?

我们要回答这个问题,首先得知道什么算是亮点?在百度百科上解释的亮点是:比喻有光彩而引人注目的人或者事务。比如说一个旧书拍卖会上,带有作者亲笔签名的书籍是本次拍卖会上的亮点。所以简单来说,亮点和闪光点是一个概念。面试官为什么会关注这个点呢? 在手机或汽车的发布会上,开发者会着重去介绍这个产品最有亮点的功能,去吸引用户购买。也就是说一个产品要想获得用户触发的购买欲望,就必须要有与众不同的点。否则,无

【生活英语】2、喜欢与讨厌

【生活英语】2、喜欢与讨厌 一、喜欢二、不喜欢三、英语对话 一、喜欢 1、I like it very much. I like it a lot. I love it. 2、I’m very fond of him. I’m fond of music. Are you into surfing? be into doing / sth. 对…感兴趣;极其喜欢

期权交易误区分享:喜欢重仓!

今天带你了解期权交易误区分享:喜欢重仓!期权交易虽然吸引人,但也有不少容易掉进去的坑。 有的投资者被单个期权的百倍利润吸引,喜欢“一口吃成胖子”。 重仓买入虚值和重度虚值的期权,当标的有大涨或大跌时,方向正确的期权上涨起来非常快,但如果有一段横盘走势,波动率下降得会很快,若标的走势和持仓方向相反,则虚值期权更容易归零,翻本的可能性也会降低。 一般来说,如果你有50万元刚刚开户,那么开始试水期

虚拟化,我喜欢

哈哈,以后就不用买那么多玩意了