倍增算法总结 ( 含RMQ模板)
部分题目来自《算法竞赛设计进阶》
问题
给定一个长度为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模板)的更多相关文章
- LCA倍增算法的错误与模板
先上我原来的错误的代码 type node=^link; link=record num:int64; next:node; end; var fa:..,..] of int64; dep:..] ...
- LCA上的RMQ模板算法
How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)To ...
- [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 ...
- LCA(最近公共祖先)之倍增算法
概述 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 如图,3和5的最近公共祖先是1,5和2的最近公共祖先是4 在本篇中我们先介 ...
- LCA倍增算法
LCA 算法是一个技巧性很强的算法. 十分感谢月老提供的模板. 这里我实现LCA是通过倍增,其实就是二进制优化. 任何一个数都可以有2的阶数实现 例如16可以由1 2 4 8组合得到 5可以由1 2 ...
- Poj 3264 Balanced Lineup RMQ模板
题目链接: Poj 3264 Balanced Lineup 题目描述: 给出一个n个数的序列,有q个查询,每次查询区间[l, r]内的最大值与最小值的绝对值. 解题思路: 很模板的RMQ模板题,在这 ...
- 后缀数组的倍增算法(Prefix Doubling)
后缀数组的倍增算法(Prefix Doubling) 文本内容除特殊注明外,均在知识共享署名-非商业性使用-相同方式共享 3.0协议下提供,附加条款亦可能应用. 最近在自学习BWT算法(Burrows ...
- [置顶] 小白学习KM算法详细总结--附上模板题hdu2255
KM算法是基于匈牙利算法求最大或最小权值的完备匹配 关于KM不知道看了多久,每次都不能完全理解,今天花了很久的时间做个总结,归纳以及结合别人的总结给出自己的理解,希望自己以后来看能一目了然,也希望对刚 ...
- CodeForces #549 Div.2 ELynyrd Skynyrd 倍增算法
题目 这道题目实际上可以用动态规划来做. 对于每个区间,我们从右边边界,往左边走,如果能走n-1次,那说明以右边边界为起点存在一个题目中说的子链. 利用倍增算法,实际上倍增也是动态规划.f[i][j] ...
随机推荐
- MySQL SQL模式特点汇总
前言 MySQL服务器可以在不同的SQL模式下运行,并且可以针对不同的客户端以不同的方式应用这些模式,具体取决于sql_mode系统变量的值.DBA可以设置全局SQL模式以匹配站点服务器操作要求,并且 ...
- RobotFrameWork+APPIUM实现对安卓APK的自动化测试----第五篇【AppiumLibrary校验函数介绍】
http://blog.csdn.net/deadgrape/article/details/50619050 以上连作者先跪一下方便面,在上一篇中,作者遗漏了两个常用的函数: 1.长按 Long P ...
- xml00
<?xml verson="1.0" encoding="ISO-8859-1"?> xml声明<note> <to>jon ...
- [Beginning SharePoint Designer 2010]探索SharePoint Designer
本章概要: 1.SharePoint Designer是如何进入到微软的工具集中去的 2.SharePoint Designer的基本特性 3.如何创建SharePoint站点 4.如何打开一个已经存 ...
- rpc框架--grpc-java
rpc框架--grpc-java grpc源码:https://github.com/grpc/grpc-java/releases/tag/v1.0.0 gradle下载:https://gradl ...
- Llama-impala on yarn的中间协调服务
本文基于CDH发行版下的Hadoop Yarn和Impala 早期的Impala版本号中.为了使用Impala.我们一般会在以Client/Server的结构在各个集群节点启动impala-serve ...
- Struts2值栈的相关操作
import org.apache.struts2.ServletActionContext; import com.opensymphony.xwork2.ActionContext; import ...
- 深入理解 C 指针阅读笔记 -- 第五章
Chapter5.h #ifndef __CHAPTER_5_ #define __CHAPTER_5_ /*<深入理解C指针>学习笔记 -- 第五章*/ /*不应该改动的字符串就应该用 ...
- linux下配置虚拟域名
linux下配置虚拟域名 1.hosts文件位置! /etc/hosts 2.增加一行 127.0.0.1 xxxxx 3.修改apache中的vhosts vi /etc/httpd/extra/h ...
- Oracle 11G R2 用exp无法导出空表解决方法
四. Oracle 10g以后增加了expdp和impdp工具,用此工具也可以导出空的表 oracleexpdp/impdp 用法详解 1) 创建逻辑目录,该命令不会在操作系统创建真正的目录,最好 ...