数字对——RMQ+二分答案
题目描述
小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
5
4 6 9 3 6
样例输出1
1 3
2
样例输入2
5
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+二分答案的更多相关文章
- [noip模拟]数字对<RMQ&二分>
数字对 [题目描述] 小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= ...
- codeforces 359D 二分答案+RMQ
上学期刷过裸的RMQ模板题,不过那时候一直不理解>_< 其实RMQ很简单: 设f[i][j]表示从i开始的,长度为2^j的一段元素中的最小值or最大值 那么f[i][j]=min/max{ ...
- [BZOJ4556][TJOI2016&&HEOI2016]字符串(二分答案+后缀数组+RMQ+主席树)
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1360 Solved: 545[S ...
- 洛谷P3957 跳房子 题解 二分答案/DP/RMQ
题目链接:https://www.luogu.org/problem/P3957 这道题目我用到了如下算法: 线段树求区间最大值: 二分答案: DP求每一次枚举答案g时是否能够找到 \(\ge k\) ...
- E. Santa Claus and Tangerines 二分答案 + 记忆化搜索
http://codeforces.com/contest/752/problem/E 首先有一个东西就是,如果我要检测5,那么14我们认为它能产生2个5. 14 = 7 + 7.但是按照平均分的话, ...
- c++二分答案 之 跳石头
题目: 题目描述 Description 一年一度的“跳石头”比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之 ...
- POJ3294--Life Forms 后缀数组+二分答案 大于k个字符串的最长公共子串
Life Forms Time Limit: 500 ...
- 【BZOJ4552】排序(线段树,二分答案)
[BZOJ4552]排序(线段树,二分答案) 题面 BZOJ 题解 好神的题啊 直接排序我们做不到 怎么维护? 考虑一下,如果我们随便假设一个答案 怎么检验它是否成立? 把这个数设成\(1\),其他的 ...
- UVA1471-Copying Books(二分答案)
Problem UVA1471-Copying Books Accept: 2669 Submit: 22797Time Limit: 3000 mSec Problem Description B ...
随机推荐
- Sublime Text 3 Build 3143 可用License
—– BEGIN LICENSE —–TwitterInc200 User LicenseEA7E-8900071D77F72E 390CDD93 4DCBA022 FAF6079061AA12C0 ...
- ThinkPad T43续命记
// Description: 原作于2016年8月25日. Mr. Robot 最近有部叫<黑客军团>(Mr. Robot)的戏比较火.目前第二季已经出到一大半了,深得技术宅和技术宅仰慕 ...
- REST-framework快速构建API--生成Swagger接口文档
一.Swagger概述 1.引言 当接口开发完成,紧接着需要编写接口文档.传统的接口文档使用Word编写,or一些接口文档管理平台进行编写,但此类接口文档维护更新比较麻烦,每次接口有变更,需要手动修改 ...
- C#_委托与事件
委托: 把方法当作参数进行传递 public delegate void AddDelegate(string name); public class Ad{ //addDelegate就是委托的一个 ...
- 快速零配置迁移 API 适配 iOS 对 IPv6 以及 HTTPS 的要求
本文快速分享一下快速零配置迁移 API 适配 iOS 对 IPv6 以及 HTTPS 的要求的方法,供大家参考. 原文发表于我的技术博客 零配置方案 最新的苹果审核政策对 API 的 IPv6 以及 ...
- 基于SimpleChain Beta的跨链交互与持续稳态思考
1. 区块链扩展性迷局 比特币作为第一个区块链应用与运行到目前为止最被信任的公链,其扩展性问题却持续被作为焦点贯穿着整个链的发展周期.事实上,在2009年1月4日比特币出现的那一天到2010年10月1 ...
- Nginx+upstream针对后端服务器容错的运维笔记
熟练掌握Nginx负载均衡的使用对运维人员来说是极其重要的!下面针对Nignx负载均衡upstream容错机制的使用做一梳理性说明: 一.nginx的upstream容错 1)nginx 判断节点失效 ...
- OpenStack构架知识梳理
OpenStack既是一个社区,也是一个项目和一个开源软件,提供开放源码软件,建立公共和私有云,它提供了一个部署云的操作平台或工具集,其宗旨在于:帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云 ...
- websocket(三)——基于node sockit.io的即时通讯
通过前面的学习发现,常见的websocket虽然可以很好地实现服务端和客户端的信息传递,但二者之间传递的数据只是简单的字符串,这对事物的描述,信息的传递是非常不友好的,下面将引入socket.io,来 ...
- PHP从入门到精通(五)
字符串三种声明方式 1."":双引号中可以解析变量"{$a}",双引号中可以使用任何转义字符:2.'':单引号中不可以解析变量,单引号中不可以使用转义字符(但是 ...