算法(未完成)

一、搜索

1.迭代加深

优化dfs,从小到大限制搜索的深度,如果在当前深度限制下搜不到答案,就把深度限制增加,重新进行一次搜索。适用于搜索树规模随着层次的深度增长很快,并且能保证答案在一个较浅层的节点。

2.估价函数

优先队列bfs:维护了一个优先队列,不断从堆中取出当前代价最小的状态(堆顶)进行扩展,每个状态第一次从堆顶取出时,就得到了初态到当前的最小代价。如果给定一个目标状态,需要求出从初态到目标态的最小代价,可以设计估价函数,以任意状态为输入,计算出从当前状态到目标状态所需代价的估价值。维护一个堆,不断取出当前代价+未来估价最小的状态进行扩展。估价函数的估值不能大于未来实际代价。

3.IDA*

估价函数与迭代加深的dfs相结合,设计一个估价函数,估算从每个状态到目标状态需要的步数,若当前深度+未来估计步数>深度限制,则立即从当前分支回溯。

二、贪心

经常使用的证明思路:不这样做得到的结果不会更优。

对于排列型表示经常考虑交换相邻元素的影响(邻项交换)。

决策包容性:证明在任何局面下,做出局部最优决策后,在问题状态空间中的可达集合包含了做出其他任何决策后的可达集合。 

范围缩放:证明任何对局部最优策略作用范围的扩展都不会导致整体结果变差。

三、二分

对于单调的函数,可以通过多次询问 f(xi) 快速找到 xt 使得 f(xt) = y。
如果满足要求的 x 不唯一,还可以找到最小/大的满足要求的 x。
许多问题可以抽象出关于询问对象的 01 函数,这个函数往往具有单调性,如当询问对象 ≥ Answer 时问题可行,当对象 < Answer 时不可行。
求 f(xi) 的过程就是判断对于 xi 是否可行。
先验证问题满足二分性质,切勿盲目二分。(三分适用于处理单峰函数)

四、倍增

1.快速幂&慢速乘

 1 unsigned long long mul(unsigned long long a,unsigned long long b) {
 2     unsigned long long ans = 0;
 3     while(b) {
 4         if(b&1)ans=(ans+a)%mod;
 5         a=(a+a)%mod;
 6         b>>=1;
 7     }
 8     return ans;
 9 }
10 unsigned long long power(unsigned long long a,unsigned long long b) {
11     unsigned long long ans=1;
12     while(b) {
13         if(b&1)ans=mul(ans,a)%mod;
14         a=mul(a,a)%mod;
15         b>>=1;
16     }
17     return ans;
18 }
View Code

2.矩阵快速幂

前置技能:矩阵乘法

 

3.ST 表

解决无修改的区间最值问题,O(NlogN)预处理,O(1)查询。

设f[i][j]表示数列A中下标在子区间[i,i + 2^j -1] 的数的最大值。

在递推时,我们把子区间的长度成倍增长,有公式F[i,j]=max(F[i,j-1].F[i+2^j,j-1),即长度为2^j的子区间的最大值是左右两半长度为2^j-1的子区间的最大值中较大的一个。

当询问任意区间[L,r]的最值时,我们先计算出一个k,满足2^k<r-l+1<2^k+1,也就是使2的k次幂小于区间长度的前提下最大的k。

那么“从l开始的2^k个数”和“以r结尾的2^k个数”这两段一定覆盖了整个区间[L,r],这两段的最大值分别是F[L,k]和F[r-2^k+1,k],二者中较大的那个就是整个区间[L,r]的最值。

因为求的是最大值,所以这两段只要覆盖区间[L,r]即可,即使有重叠也没关系。

(此处代码求的为最小值)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<string>
 5 #include<cstring>
 6 #include<algorithm>
 7 #include<iomanip>
 8 using namespace std;
 9 namespace Moxing{
10     const int N=1e5+5;
11     int m,n,t;long long f[N][18],a[N];
12     void ST_prework(){
13         for(int i = 1; i <= n; i++){
14             f[i][0] = a[i];
15         }
16         t=log(n)/log(2)+1;
17         for(int i = 1; i <= t; i++){
18             for(int j = 1; j <= n-(1<<i)+1; j++){
19                 f[j][i] = min(f[j][i-1],f[j+(1<<(i-1))][i-1]);
20             }
21         }
22     }
23     long long ST_query(int l,int r){
24         int k = log(r-l+1)/log(2);
25         return min(f[l][k],f[r-(1<<k)+1][k]);
26     }
27     struct main{
28         main(){
29             memset(f,0x3f,sizeof(f));
30             scanf("%d%d",&n,&m);
31             for(int i = 1; i <= n; i++){
32                 scanf("%lld",&a[i]);
33             }
34             ST_prework();
35             int l,r;
36             for(int i = 1; i <= m; i++){
37                 scanf("%d%d",&l,&r);
38                 printf("%lld ",ST_query(l,r));
39             }
40             exit(0);
41         }
42     }UniversalLove;
43 }
44 int main(){
45     Moxing::main();
46 }
View Code

4.LCA

5.其他

在递推时,我们把子区间的长度成倍增长,有公式F[,]=max(F[i,j-1].F[i+21j-11),即长度为2/的子区间的最大值是左右两半长度为2/-1的子区间的最大值中较大的一个。当询问任意区间[L,r]的最值时,我们先计算出一个k,满足2*<r-l+1s2*+1,也就是使2的k次幂小于区间长度的前提下最大的k。那么“从l开始的24个数”和“以r结尾的2*个数”这两段一定覆盖了整个区间[L,r],这两段的最大值分别是FL,k]和F[r-2*+1,k],二者中较大的那个就是整个区间L,r]的最值。因为求的是最大值,所以这两段只要覆盖区间[L,r]即可,即使有重叠也没关系,

转载于:https://www.cnblogs.com/Moxingtianxia/p/11334064.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值