上学期刷过裸的RMQ模板题,不过那时候一直不理解>_<

其实RMQ很简单:

设f[i][j]表示从i开始的,长度为2^j的一段元素中的最小值or最大值

那么f[i][j]=min/max{d[i][j-1], d[i+2^j-1][j-1]}

RMQ的ST算法:

 void ST()        //初始化
{
memset(RMQ,,sizeof(RMQ)); for(int i=;i<=n;i++)
RMQ[i][]=a[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<=n;i++)
RMQ[i][j]=min(RMQ[i][j-],RMQ[i+(<<(j-))][j-]);
} int Query(int L,int R) //求a[L..R]区间的最值
{
int k=;
while((<<(k+))<=R-L+) k++;
int tb=gcd(GCD[L][k],GCD[R-(<<k)+][k]);
return tb;
}

-----------------------------------------------

再回到这道题。要求输出r-l的最大值

可以使用二分答案。

注意:r-l的值可以为0(即r==l),可以这样写:

         l=;    r=n;
while (r>=l)
{
int mid=(l+r)/; //mid: r-l
if (calc(mid)) //calc(mid): 判断mid答案是否符合要求
l=mid+;
else
r=mid-;
}

记得原来还刷过求最小值的二分答案(NOIP2010提高组  关押罪犯),是这样的:

 //当年的代码略屎= =

 sol:=false;
l:=; r:=mx;
while l<r do
begin
mid:=(l+r) div ;
ok:=process(mid);
if ok then
begin
sol:=true;
r:=mid;
end
else
begin
l:=mid+;
sol:=true;
end;
end;

----------------------------------------

如何求区间所有元素的gcd?

不难想出,其实gcd和min(求区间最小值)有个一样的性质:

设在区间[l..r]中,[l..k]的gcd为m,[k+1..r]的gcd为n,

则整个区间[l..r]的gcd等于gcd(m,n)

有了这个性质,就可以用ST算法求gcd了。

-------------------------------------------

借用了neopenx大神的RMQ模板,Orz

 #include <iostream>
#include <vector>
#include <cstring>
using namespace std; vector<int> ans;
int RMQ[][],GCD[][];
int T,n,l,r,mx,num;
int a[]; int gcd(int x,int y)
{
return (y==)?x:gcd(y,x%y);
} void ST()
{
memset(RMQ,,sizeof(RMQ));
memset(GCD,,sizeof(GCD)); for(int i=;i<=n;i++)
RMQ[i][]=GCD[i][]=a[i];
for(int j=;(<<j)<=n;j++)
for(int i=;i+(<<j)-<=n;i++)
{
RMQ[i][j]=min(RMQ[i][j-],RMQ[i+(<<(j-))][j-]);
GCD[i][j]=gcd(GCD[i][j-],GCD[i+(<<(j-))][j-]);
}
} bool Query(int L,int R)
{
if (L==R) return true;
int k=;
while((<<(k+))<=R-L+) k++;
int ta=min(RMQ[L][k],RMQ[R-(<<k)+][k]);
int tb=gcd(GCD[L][k],GCD[R-(<<k)+][k]);
if (ta==tb) return true;
else return false;
} bool calc(int x) //x: r-l
{
bool res=false;
for (int i=;i<=n-x;i++)
{
bool ok=Query(i,i+x);
if (ok)
{
res=true;
//cout<<"----"<<i<<" "<<i+x<<" "<<x<<endl; //record the answer,use vector
if (x==mx)
{
num++;
ans.push_back(i);
}
else if (x>mx)
{
num=;
mx=x;
ans.clear();
ans.push_back(i);
}
}
}
return res;
} int main()
{
mx=-;
num=;
ans.clear();
cin>>n;
for (int i=;i<=n;i++)
cin>>a[i]; ST(); l=; r=n;
while (r>=l)
{
int mid=(l+r)/; //mid: r-l
if (calc(mid))
l=mid+;
else
r=mid-;
}
cout<<num<<" "<<mx<<endl;
vector<int>::iterator ii;
for (ii=ans.begin();ii!=ans.end();ii++)
cout<<*ii<<" ";
cout<<endl; return ;
} /*
注意特殊情况:
5
2 3 5 7 11
计算时应把r-l=0也考虑进去
(r==l)
*/

codeforces 359D 二分答案+RMQ的更多相关文章

  1. Codeforces Round #425 (Div. 2) Problem C Strange Radiation (Codeforces 832C) - 二分答案 - 数论

    n people are standing on a coordinate axis in points with positive integer coordinates strictly less ...

  2. Electric Charges CodeForces - 623C (二分答案)

    大意: 平面上n个点每个点坐标为(x,0)或(0,y), 求任意两点距离平方最大值的最小值. 二分答案, 转化为判定最大值是否<=e, 按$x$排序后, 因为固定左端点, $y$绝对值的最大值是 ...

  3. Codeforces 1132D(二分答案+堆)

    题面 传送门 分析 二分答案,考虑如何判定 可以用贪心的方法,每次找最快没电的电脑,在没电前1单位时间给它充电 正确性显然 实现上可以维护一个堆,存储每个电脑电用完的时刻,每次从堆顶取出最小的一个给它 ...

  4. CodeForces 483B 二分答案

    题目: B. Friends and Presents time limit per test 1 second memory limit per test 256 megabytes input s ...

  5. CodeForces 549H | 二分答案

    参考了这个博客哇 #include<cstdio> #include<algorithm> #include<cstring> #define Max(a,b,c, ...

  6. CodeForces 359D (数论+二分+ST算法)

    题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=47319 题目大意:给定一个序列,要求确定一个子序列,①使得该子序 ...

  7. Codeforces 700A As Fast As Possible(二分答案)

    [题目链接] http://codeforces.com/problemset/problem/700/A [题目大意] 有一辆限载k人速度为v2的车,n个步行速度均为v1的人要通过一段长度为l的距离 ...

  8. Codeforces Round #276 (Div. 1) E. Sign on Fence (二分答案 主席树 区间合并)

    链接:http://codeforces.com/contest/484/problem/E 题意: 给你n个数的,每个数代表高度: 再给出m个询问,每次询问[l,r]区间内连续w个数的最大的最小值: ...

  9. Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) Problem D (Codeforces 831D) - 贪心 - 二分答案 - 动态规划

    There are n people and k keys on a straight line. Every person wants to get to the office which is l ...

随机推荐

  1. linux启动jmeter,执行./jmeter.sh报错解决方法

    1.l-bash: ./jmeter.sh: Permission denied解决办法:jmeter.sh的执行权限改改,是权限不够chmod 777 jmeter.sh 2.An error oc ...

  2. Android中Intent传递对象的两种方法(Serializable,Parcelable)

    今天要给大家讲一下Android中 Intent中如何传递对象,就我目前所知道的有两种方法,一种是Bundle.putSerializable(Key,Object);另一种是 Bundle.putP ...

  3. cotangent Laplacian

    几何网格处理经常用到 cotangent laplacian矩阵.前几天把这个功能整合到我的Maya 转 Matlab插件了. 这里发一个利用cotangent laplacian计算特征向量并显示的 ...

  4. javascript:让表单 文本框 只读,不可编辑的方法

    有时候,我们希望表单中的文本框是只读的,让用户不能修改其中的信息,如使<input type="text" name="input1" value=&qu ...

  5. 一篇文章告诉你为何GitHub估值能达20亿美元

    软件开发平台GitHub今日宣布,已获得硅谷多家知名风投2.5亿美元融资,这也让其融资总额达到了3.5亿美元,此轮融资对GitHub的估值约为20亿美元. GitHub有何特别之处? GitHub创立 ...

  6. 如何在Web服务器80端口上开启SSH服务

    本文所讨论的网络端口复用并非指网络编程中采用SO_REUSEADDR选项的 Socket Bind 复用.它更像是一个带特定路由功能的端口转发工具,在应用层实现. 背景 笔者所处网络中防火墙只开放了一 ...

  7. c语言 &取地址运算符的理解

    对于c语言中的&运算符,百度百科是这样定义的:(&p)则是这样一种运算,返回当时声明p 时开辟的地址:但是根据我对代码的观察,我觉得&运算符不只是返回地址的功能: 例如: in ...

  8. U3D5.3.5f Monodevelop 仅支持到.NET 3.5

    2016年12月2号:发现这个标题是错误的,可以在monodevelop中选择.NET的版本,如下:打开solution,右击 Assembly-CSharp,options, build, gene ...

  9. Google protocol buffer在windows下的编译

    在caffe框架中,使用的数据格式是google的 protocol buffer.对这个不了解,所以,想简单学习一下.简单来说,Protocol Buffer 是一种轻便高效的结构化数据存储格式,可 ...

  10. Edittext焦点处理

    <LinearLayout android:focusable="true" android:layout_width="0dp" android:lay ...