部分题目来自《算法竞赛设计进阶》

问题

      给定一个长度为n的数列A,有m个询问,每次给定一个整数T,求出最大的k,满足a[1],a[2]……a[k]的和小于等于T(不会打sigma)

第一反应是二分,这个时候的复杂度是logn

还有第二种解法,用倍增的思想,复杂度为logk(所求答案)。显然倍增要好很多。我讲讲倍增。

如果是暴力的话显然是从前往后一个一个枚举来计算。这里每次只往后移了一格,我们能不能一下子移很多格呢?

当然可以,我们可以用倍增的思想,第一次移1格,第二次移2格……如果再移就超过答案,就把移的格数除以2。如果最后移的格数是0,那么这一格就是答案

#include<cstdio>
#include<cctype>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; const int MAXN = + ;
int a[MAXN], s[MAXN], n, m, sum; void read(int& x)
{
int f = ; x = ; char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -; ch = getchar(); }
while(isdigit(ch)) { x = x * + ch - ''; ch = getchar(); }
x *= f;
} int main()
{
read(n); read(m);
_for(i, , n) read(a[i]), s[i] = s[i-] + a[i];
while(m--)
{
int T; read(T);
int k = , p = , sum = ; //k为当前在哪一格,p为下一步要移多少格,sum为已经走了的格的总和
while(p)
{
if(k + p <= n && sum + s[k + p] - s[k] <= T)
{
sum += s[k + p] - s[k];
k += p;
p <<= ;
}
else p >>= ;
}
printf("%d\n", k);
}
return ;
}

hihocoder#1384

发现倍增的套路和二分有点像。出题就出来判断区间是否合法上

这里值得一提的是可以把新加进入的数组sort一遍,然后和之前已经

有序的数组做一次归并,而不用从头再来sort

//这个程序WA,目前还不知道为什么
#include<cstdio>
#include<algorithm>
#include<cctype>
#include<cmath>
#define REP(i, a, b) for(register int i = (a); i < (b); i++)
#define _for(i, a, b) for(register int i = (a); i <= (b); i++)
using namespace std; typedef long long ll;
const int MAXN = 5e5 + 10;
int n, m, a[MAXN];
int b[MAXN], t[MAXN];
ll T; inline void read(int& x)
{
int f = 1; x = 0; char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
x *= f;
} inline void readll(ll& x)
{
ll f = 1; x = 0; char ch = getchar();
while(!isdigit(ch)) { if(ch == '-') f = -1; ch = getchar(); }
while(isdigit(ch)) { x = x * 10 + ch - '0'; ch = getchar(); }
x *= f;
} void merge_sort(int L, int R, int p)
{
_for(i, R + 1, R + p) b[i] = a[i];
sort(b + R + 1, b + R + p + 1); int i = L, pos = L, j = R + 1;
while(i <= R || j <= R + p)
{
if(j > R + p || i <= R && a[i] < b[j]) t[pos++] = a[i++];
else t[pos++] = b[j++];
}
_for(i, L, R + p) a[i] = t[i];
} bool check(int L, int R, int p)
{
merge_sort(L, R, p);
ll res = 0;
int l = L, r = R + p, tmp = m;
while(tmp--)
{
if(l >= r) break;
res += (a[r] - a[l]) * (a[r] - a[l]);
if(res > T) return false;
r--; l++;
}
return true;
} int main()
{
int t; read(t);
while(t--)
{
read(n); read(m); readll(T);
_for(i, 1, n) read(a[i]); int L = 1, R, ans = 0, p;
while(L <= n)
{
R = L; p = 1;
ans++;
while(p)
{
if(R + p <= n && check(L, R, p)) //
{
R += p;
p <<= 1;
}
else p >>= 1;
}
L = R + 1;
}
printf("%d\n", ans);
} return 0;
}

RMQ算法模板 poj 3264(快速求区间最值,不支持修改)

#include<cstdio>
#include<algorithm>
#define REP(i, a, b) for(int i = (a); i < (b); i++)
#define _for(i, a, b) for(int i = (a); i <= (b); i++)
using namespace std; const int MAXN = 8e4;
const int MAXM = 30;
int dmin[MAXN][MAXM], dmax[MAXN][MAXM], a[MAXN], n, q; void RMQ_init()
{
_for(i, 1, n) dmin[i][0] = dmax[i][0] = a[i];
for(int j = 1; (1 << j) <= n; j++)
for(int i = 1; i + (1 << j) - 1 <= n; i++)
{
dmax[i][j] = max(dmax[i][j-1], dmax[i + (1 << (j-1))][j-1]);
dmin[i][j] = min(dmin[i][j-1], dmin[i + (1 << (j-1))][j-1]);
}
} int RMQ_ans(int l, int r)
{
int k = 0;
while((1 << (k + 1)) <= r - l + 1) k++;
return max(dmax[l][k], dmax[r - (1 << k) + 1][k]) - min(dmin[l][k], dmin[r - (1 << k) + 1][k]);
} int main()
{
scanf("%d%d", &n, &q);
_for(i, 1, n) scanf("%d", &a[i]);
RMQ_init();
while(q--)
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", RMQ_ans(l, r));
}
return 0;
}

倍增算法总结 ( 含RMQ模板)的更多相关文章

  1. LCA倍增算法的错误与模板

    先上我原来的错误的代码 type node=^link; link=record num:int64; next:node; end; var fa:..,..] of int64; dep:..] ...

  2. LCA上的RMQ模板算法

    How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  3. [CF 191C]Fools and Roads[LCA Tarjan算法][LCA 与 RMQ问题的转化][LCA ST算法]

    参考: 1. 郭华阳 - 算法合集之<RMQ与LCA问题>. 讲得很清楚! 2. http://www.cnblogs.com/lazycal/archive/2012/08/11/263 ...

  4. LCA(最近公共祖先)之倍增算法

    概述 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4 在本篇中我们先介 ...

  5. LCA倍增算法

    LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...

  6. Poj 3264 Balanced Lineup RMQ模板

    题目链接: Poj 3264 Balanced Lineup 题目描述: 给出一个n个数的序列,有q个查询,每次查询区间[l, r]内的最大值与最小值的绝对值. 解题思路: 很模板的RMQ模板题,在这 ...

  7. 后缀数组的倍增算法(Prefix Doubling)

    后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...

  8. [置顶] 小白学习KM算法详细总结--附上模板题hdu2255

    KM算法是基于匈牙利算法求最大或最小权值的完备匹配 关于KM不知道看了多久,每次都不能完全理解,今天花了很久的时间做个总结,归纳以及结合别人的总结给出自己的理解,希望自己以后来看能一目了然,也希望对刚 ...

  9. CodeForces #549 Div.2 ELynyrd Skynyrd 倍增算法

    题目 这道题目实际上可以用动态规划来做. 对于每个区间,我们从右边边界,往左边走,如果能走n-1次,那说明以右边边界为起点存在一个题目中说的子链. 利用倍增算法,实际上倍增也是动态规划.f[i][j] ...

随机推荐

  1. JavaScript(正则表达式一)

    -------------------- 创建正则表达式: 验证匹配的两个方法 //正则表达式测试 /* var p=new RegExp("Box","i") ...

  2. jquery-ajax基础-XMLHttpRequest

    XMLHttpRequest知识点 原生的ajax代码 var xmlhttp; // 声明一个对象 if (window.XMLHttpRequest) {// code for IE7+, Fir ...

  3. 洛谷—— P1262 间谍网络

    https://www.luogu.org/problem/show?pid=1262 题目描述 由于外国间谍的大量渗入,国家安全正处于高度的危机之中.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A ...

  4. Shell简单介绍

    Shell是一种具备特殊功能的程序.它是介于使用者和linux 操作系统之核心程序(kernel)间的一个接口.为什么我们说 shell 是一种介于系统核心程序与使用者间的中介者呢?读过操作系统概论的 ...

  5. sqlite学习笔记7:C语言中使用sqlite之打开数据库

    数据库的基本内容前面都已经说得差点儿相同了.接下看看如何在C语言中使用sqlite. 一 接口 sqlite3_open(const char *filename, sqlite3 **ppDb) 打 ...

  6. hadoop(七) - hadoop集群环境搭建

    一. 前言: hadoop2.0已经公布了稳定版本号了,添加了非常多特性,比方HDFS HA.YARN等.最新的hadoop-2.4.1又添加了YARN HA 注意:apache提供的hadoop-2 ...

  7. Django迁移到mysql数据库时的错误

    pip install mysqlclient Collecting mysqlclient Using cached https://files.pythonhosted.org/packages/ ...

  8. docker中出现容器未运行无法进入容器的操作

  9. ROS-参数

    前言:参数的用法. 一.参数常用命令 命令 功能 rosparam list 参数列表 rosparam get 获取参数 rosparam set  设置参数 rosparam load 加载参数 ...

  10. mybatis的sql语句导致索引失效,使得查询超时

    mybaitis书写sql需要特别注意where条件中的语句,否则将会导致索引失效,使得查询总是超时.如下语句会出现导致索引失效的情况: with test1 as (select count(C_F ...