上学期刷过裸的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命令学习-sed

    sed是一个很好的文件处理工具,本身是一个管道命令,主要是以行为单位进行处理,可以将数据行进行替换.删除.新增.选取等特定工作,下面先了解一下sed的用法sed命令行格式为:         sed ...

  2. android strings.xml 报 is not translated in af,

    57 down vote In your ADT go to window->Preferences->Android->Lint Error Checking Find there ...

  3. static,静态关键字的详解

    一,使用static声明属性 class Person{ // 定义Person类 String name ; // 定义name属性,暂时不封装 int age ; // 定义age属性,暂时不封装 ...

  4. Jsp页显示时间标签JSTL标签 <fmt:formatDate/> 实例大全

    <fmt:formatDate value="${isoDate}" type="both"/>2004-5-31 23:59:59 <fmt ...

  5. yslow性能优化的35条黄金守则

    参考Best Practices for Speeding Up Your Web Site Exceptional Performance 团队总结了一系列优化网站性能的方法,分成了7个大类35条, ...

  6. wireshark排查打印机问题

    抓包工具排除故障 前言:上网慢,可能是内网堵了.装上wireshark,可抓到广播包,多播包,以及发给自己的包.如果想抓lan内其他人之间的通信包,那就要在sw上做端口镜像. 背景 调试打印机的人发现 ...

  7. Linux Linux程序练习九

    题目:利用多线程与有名管道技术,实现两个进程之间发送即时消息,实现聊天功能 思路:关键在于建立两个有名管道,利用多线程技术,进程A中线程1向管道A写数据,进程B中线程2从管道A读数据,进程A线程2从管 ...

  8. C#把某个数组的一部分复制到另一个数组中的两种方法:Buffer.BlockCopy和Array.Copy

    static void Main(string[] args) { , , , , , }; ;//目标数组大小 int int_size = sizeof(int);//用于获取值类型的字节大小. ...

  9. sql语句or与union all的执行效率比较

    看到一篇文章是讲sql语句or与union all的执行效率比较的,以前没怎么注意这个问题,感觉文章写的不错,转来一看. 文章原链接:http://www.cunyoulu.com/zhuanti/q ...

  10. 封装WCF客户端调用

    在之前的博客中,我记录过如何利用SvcUtil.exe工具生成客户端的代理文件,然后调用的情形. 今天我要讲解的是利用代码直接对服务端进行调用.好处在于,一是不会生成那么大的引用文件,其次是可以方便控 ...