黑科技 莫队 “亡羊补牢”

这名字···

这个算法是由之前的国家队队长莫涛巨神(Orz….%%%64)发明的,所以尊称莫队算法。

莫队算法

事实上,莫队算法这种东西,应该叫做——

一个优雅的暴力(引自Alan_Cty)

传说中能解决一切区间问题的算法

如果我们知道区间[L,R],就能在O(1)求出[L−1,R],[L+1,R],[L,R−1],[L,R+1]的话,那就可以用莫队算法了。

有一种经典的问题:给你一些不带修改的区间询问,要求快速回答

显然,有一些我们可以通过线段树来完成,因为线段树是O(NlogN)的

但是,线段树有的东西是维护不了的。

看一个例子

给你一个数列,若干询问,要求回答区间内同种颜色大小。

线段树很难做,怎么办?

用莫队算法!

莫队算法的实质是通过将询问排序,每个询问均由前一个询问(排序后的)转移得来,通过一定的排序优化时间复杂度。往往可以有O(NN−−√)的效果

回到题目
显然对于两次询问L,R和L′,R′,知道了L,R的答案,就可以暴力计算|L−L′|+|R−R′|次得出L′,R′的答案。

|L−L′|+|R−R′|。这个东西,数学上称之为曼哈顿距离

把每个询问看作是二维平面上的点,那么我们的最小总时间,就是这些点的最小曼哈顿距离生成树, 按照这个树的顺序做,复杂度变成了O(NN−−√)(为什么?不好意思,我不会证),而且这个生成树连边也有特别的技巧,可以去看莫队在知乎上推荐的那篇。

然而这样有一点猥琐

有一个优美方便简洁好理解的替代品

分块大法好!

把整个序列分块,把L按照所在块的顺序为第一关键字,把R(R本身!)为第二关键字排序。

为什么要分块不能直接排呢?

分块很好的减少了一种情况的影响。

L

引用自

雷锋

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的实现这个功能的Android应用程序: 1. 在activity_main.xml文件中添加一个TextView和一个Button控件: ```xml <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.randomword.MainActivity"> <TextView android:id="@+id/tv_word" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="24sp" android:text="@string/default_word" /> <Button android:id="@+id/btn_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/btn_next" /> </RelativeLayout> ``` 2. 在MainActivity.java文件中添加以下代码: ```java public class MainActivity extends AppCompatActivity { private TextView tvWord; private Button btnNext; private String[] words = {"抱头鼠窜", "胸无点墨", "如鱼得水", "头破血流", "鼠目寸光", "狗急跳墙", "亡羊补牢"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvWord = (TextView) findViewById(R.id.tv_word); btnNext = (Button) findViewById(R.id.btn_next); btnNext.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { int index = (int) (Math.random() * words.length); tvWord.setText(words[index]); } }); } } ``` 这个应用程序中,我们使用了一个String类型的数组来存储所有的词汇,然后通过Math.random()方法来随机获取一个词汇,并将其显示在TextView控件上。每次点击Button按钮时都会更新TextView的文本内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值