数字对——RMQ+二分答案

时间:2021-12-30 19:14:10

题目描述 
小H是个善于思考的学生,现在她又在思考一个有关序列的问题。

她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= n)。

这个特殊区间满足,存在一个k(L <= k <= R),并且对于任意的i(L <= i <= R),ai都能被ak整除。这样的一个特殊区间 [L, R]价值为R - L。

小H想知道序列中所有特殊区间的最大价值是多少,而有多少个这样的区间呢?这些区间又分别是哪些呢?你能帮助她吧。

输入 
第一行,一个整数n.

第二行,n个整数,代表ai.

输出 
第一行两个整数,num和val,表示价值最大的特殊区间的个数以及最大价值。

第二行num个整数,按升序输出每个价值最大的特殊区间的L.

样例输入1 

4 6 9 3 6 
样例输出1 
1 3 

样例输入2 

2 3 5 7 11 
样例输出2 
5 0 
1 2 3 4 5

数据范围

30%: 1 <= n <= 30 , 1 <= ai <= 32.

60%: 1 <= n <= 3000 , 1 <= ai <= 1024.

80%: 1 <= n <= 300000 , 1 <= ai <= 1048576.

100%: 1 <= n <= 500000 , 1 <= ai < 2 ^ 31.

这道题主要求的是最长区间长度,可以发现它是具有单调性的:对于一段区间,如果它是特殊区间,那么它一定有子区间是特殊区间。因此我们可以二分最长区间长度,对于每个二分出来的答案进行验证。那么怎么验证?可以发现特殊区间有几个很好的性质:1、ak一定是这段区间的最小值,因为如果有一个数ai比ak小,那ai一定不能被ak整除。2、ak一定是区间gcd,因为将所有ai都除以ak后,这段区间就变成了1,b1,b2……这些数gcd显然是1,再乘回ak后gcd就是ak了。那么只要比较一段区间最小值和gcd是否相同就能判断是否是特殊区间了。但如果暴力找区间最小值和区间gcd显然是不行的,因此要用ST表预处理出来g[i][j]和m[i][j]分别表示以j为起点往后2^i个数的gcd和最小值。再对于每个答案O(n)遍历所有起点判断并记录下来每个特殊区间的起点就OK了。每次验证是O(nlogn),总时间复杂度是O(n*(logn)^2)。

最后附上代码。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
using namespace std;
int g[20][500010];
int m[20][500010];
int a[500010];
int l[500010];
int n;
int L,R;
int ans;
int cnt;
int q[500010];
int flag;
int gcd(int x,int y)
{
if(x<y)
{
swap(x,y);
}
if(y!=0)
{
return gcd(y,x%y);
}
else
{
return x;
}
}
bool check(int x)
{
cnt=0;
for(int i=1;i+x-1<=n;i++)
{
int s=l[x];
if(gcd(g[s][i],g[s][i+x-(1<<s)])==min(m[s][i],m[s][i+x-(1<<s)]))
{
q[++cnt]=i;
}
}
if(cnt!=0)
{
ans=max(ans,x);
return true;
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
g[0][i]=a[i];
m[0][i]=a[i];
}
for(int i=1;(1<<i)<=n;i++)
{
for(int j=1;j+(1<<(i-1))<=n;j++)
{
g[i][j]=gcd(g[i-1][j],g[i-1][j+(1<<(i-1))]);
m[i][j]=min(m[i-1][j],m[i-1][j+(1<<(i-1))]);
}
}
for(int i=2;i<=n;i++)
{
l[i]=l[i>>1]+1;
}
L=1;
R=n;
while(L<R-1)
{
int mid=(L+R)>>1;
if(check(mid)==true)
{
L=mid;
}
else
{
R=mid;
}
}
bool o1=check(L);
bool o2=check(R);
bool o3=check(ans);
printf("%d %d\n",cnt,ans-1);
for(int i=1;i<=cnt;i++)
{
if(flag==0)
{
printf("%d",q[i]);
flag=1;
}
else
{
printf(" %d",q[i]);
}
}
}

数字对——RMQ+二分答案的更多相关文章

  1. &lbrack;noip模拟&rsqb;数字对&lt&semi;RMQ&amp&semi;二分&gt&semi;

    数字对 [题目描述] 小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= ...

  2. codeforces 359D 二分答案&plus;RMQ

    上学期刷过裸的RMQ模板题,不过那时候一直不理解>_< 其实RMQ很简单: 设f[i][j]表示从i开始的,长度为2^j的一段元素中的最小值or最大值 那么f[i][j]=min/max{ ...

  3. &lbrack;BZOJ4556&rsqb;&lbrack;TJOI2016&amp&semi;&amp&semi;HEOI2016&rsqb;字符串&lpar;二分答案&plus;后缀数组&plus;RMQ&plus;主席树&rpar;

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 1360  Solved: 545[S ...

  4. 洛谷P3957 跳房子 题解 二分答案&sol;DP&sol;RMQ

    题目链接:https://www.luogu.org/problem/P3957 这道题目我用到了如下算法: 线段树求区间最大值: 二分答案: DP求每一次枚举答案g时是否能够找到 \(\ge k\) ...

  5. E&period; Santa Claus and Tangerines 二分答案 &plus; 记忆化搜索

    http://codeforces.com/contest/752/problem/E 首先有一个东西就是,如果我要检测5,那么14我们认为它能产生2个5. 14 = 7 + 7.但是按照平均分的话, ...

  6. c&plus;&plus;二分答案 之 跳石头

    题目: 题目描述 Description 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之 ...

  7. POJ3294--Life Forms 后缀数组&plus;二分答案 大于k个字符串的最长公共子串

                                                                              Life Forms Time Limit: 500 ...

  8. 【BZOJ4552】排序(线段树,二分答案)

    [BZOJ4552]排序(线段树,二分答案) 题面 BZOJ 题解 好神的题啊 直接排序我们做不到 怎么维护? 考虑一下,如果我们随便假设一个答案 怎么检验它是否成立? 把这个数设成\(1\),其他的 ...

  9. UVA1471-Copying Books(二分答案)

    Problem UVA1471-Copying Books Accept: 2669  Submit: 22797Time Limit: 3000 mSec Problem Description B ...

随机推荐

  1. angularjs中ng-controller中绑定对象

    <!DOCTYPE HTML><html ng-app="myApp"><head><meta http-equiv="Cont ...

  2. HTML、canvas、video灰度

    效果图: 注:本例需在服务器上运行的才能看到效果.视频文件可换成本地视频(HBuilder有集成服务器或者使用wampmanager). 代码如下: <!DOCTYPE html> &lt ...

  3. laravel url&lpar;&rpar; 和 asset&lpar;&rpar; 的区别

    asset()方法用于引入 CSS/JavaScript/images 等文件,文件必须存放在public文件目录下.url()方法生成一个完整的网址.

  4. css3实现钟表特效

    <!doctype html><html><head><meta http-equiv="Content-Type" content=&q ...

  5. Duplicate files copied in APK META-INF&sol;LICENSE&period;txt

    Error:Execution failed for task ':app:packageDebug'. > Duplicate files copied in APK META-INF/LIC ...

  6. 银河麒麟操作系统U盘手动挂载,出现乱码

    使用银河麒麟操作系统,U盘手动挂载,U盘中中文字符显示为乱码??      对于银河麒麟操作系统的这一问题,可能是因为字符集的原因,需要在mount后加参数: sudo mount –o iochar ...

  7. &lbrack;福大软工&rsqb; W班 软工实践原型设计—成绩公布

    作业地址 https://edu.cnblogs.com/campus/fzu/FZUSoftwareEngineering1715W/homework/909 作业要求 详见作业地址 存在问题 1. ...

  8. Beta冲刺NO&period;5

    Beta冲刺 第五天 1. 昨天的困难 1.昨天的困难主要是在类的整理上,一些逻辑理不清,也有一些类写的太绝对了,扩展性就不那么好了,所以,昨天的困难就是在重构上. 页面结构太凌乱,之前没有统筹好具体 ...

  9. MAKEWORD 宏(macro)

    先看看Microsoft给出的关于MAKEWORD的参考: 从Microsoft给出的参考可以得知,宏MAKEWORD的作用是用于创建一个由bHigh和bLow组成的WORD类型的值. 其中bLow是 ...

  10. Exp6 20155218 信息搜集与漏洞扫描

    Exp6 信息搜集与漏洞扫描 1.DNS IP注册信息的查询 1.进行whois查询时,要去掉www,ftp等前缀,否则可能在whois服务器中查询不到: 2.使用whois查询ip的地理位置: 2. ...