题目链接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=47319

题目大意:给定一个序列,要求确定一个子序列,①使得该子序列中所有值都能被其中一个值整除,②且子序列范围尽可能大(r-l尽可能大)。

解题思路

对于要求1,不难发现只有min(L,R)=gcd(L,R)时才行。其中gcd是L,R范围内的最大公约数,min是L,R范围内的最小值。

对于要求2,传统思路是r-l从大到小枚举,每次确定一个(L,R)范围,进行判断,直到可行。复杂度O(n^2)铁定TLE。

由于r-l的值是有序的,固采用二分。先枚举r-l的中间值,如果符合要求,则向右考虑,看看有没有更大的。否则向左。

当然这题的难度不止于此,尽管采用二分,但是光是枚举复杂度就有O(nlogn)了,再加上查询orz。

最初我使用的是线段树完成RMQ、以及GCD的Query , 复杂度O(n*logn*logn), CF跑到Test10就TLE了。

看了题解才发现要使用ST算法在O(1)的时间内完成RMQ和GCD。也是第一次碰到ST算法,看见刘汝佳的炒鸡简洁ST,给跪了。

#include "cstdio"
#include "iostream"
#include "vector"
#include "algorithm"
#include "math.h"
#include "cstring"
using namespace std;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define maxn 3*100005
#define maxp 20
template <class T>
inline bool read(T &ret)
{
char c;
int sgn;
if(c=getchar(),c==EOF) return ; //EOF
while(c!='-'&&(c<''||c>'')) c=getchar();
sgn=(c=='-')?-:;
ret=(c=='-')?:(c-'');
while(c=getchar(),c>=''&&c<='') ret=ret*+(c-'');
ret*=sgn;
return ;
}
int gcd(int a,int b) {if(b!=) return gcd(b,a%b);else return a;}
int RMQ[maxn][maxp],GCD[maxn][maxp],val[maxn],n,cnt,range;
vector<int> ans;
void ST()
{
for(int i=;i<=n;i++) RMQ[i][]=GCD[i][]=val[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)
{
int k=;
while((<<(k+))<=R-L+) k++;
int a=min(RMQ[L][k],RMQ[R-(<<k)+][k]);
int b=gcd(GCD[L][k],GCD[R-(<<k)+][k]);
if(a==b) return true;
else return false;
}
bool judge(int v) //枚举r-l
{
int cc=;
vector<int> tt;
for(int i=; v+i<=n; i++)
{
if(Query(i,i+v)) //L=i,R=i+v;
{
cc++;
tt.push_back(i);
}
}
if(cc>)
{
ans=tt;
cnt=cc;
range=v;
return true;
}
return false;
}
int main()
{
memset(RMQ,,sizeof(RMQ));
memset(GCD,,sizeof(GCD));
read(n);
for(int i=; i<=n; i++)
read(val[i]);
ST();
int l=,r=n-,mid;
while(l<=r) //二分
{
mid=(l+r)>>;
if(judge(mid)) l=mid+;
else r=mid-;
}
printf("%d %d\n",cnt,range);
for(int i=;i<ans.size();i++) {if(i>) printf(" ");printf("%d",ans[i]);};
printf("\n");
}
2808371 neopenx CodeForces 359D Accepted 51924 KB 358 ms GNU C++ 4.6 1981 B 2014-10-03 15:00:32

CodeForces 359D (数论+二分+ST算法)的更多相关文章

  1. codeforces 359D 二分答案+RMQ

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

  2. HDU 5289 Assignment (ST算法区间最值+二分)

    题目链接:pid=5289">http://acm.hdu.edu.cn/showproblem.php?pid=5289 题面: Assignment Time Limit: 400 ...

  3. 【原创】RMQ - ST算法详解

    ST算法: ID数组下标: 1   2   3   4   5   6   7   8   9    ID数组元素: 5   7   3   1   4   8   2   9   8 1.ST算法作 ...

  4. hdu5289 Assignment (区间查询最大值最小值,st算法...)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5289 题意:给定长度为n的序列a和一个整数K,找出最大值和最小值的差值小于K的区间.输出满足条件的区间的个 ...

  5. AcWing ST算法(区间求最值)打卡

    一,介绍 ST算法是一个用倍增来求区间最值的算法,倍增是一个与二分类似的思想的一个东西,倍增简而言之也就是区间长度按1,2,4,8..... 我们先用nlog(n)的复杂度打出一个最大值表,后面我们可 ...

  6. Java实现的二分查找算法

    二分查找又称折半查找,它是一种效率较高的查找方法. 折半查找的算法思想是将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小 于该中点 ...

  7. c#-二分查找-算法

    折半搜索,也称二分查找算法.二分搜索,是一种在有序数组中查找某一特定元素的搜索算法. A 搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束: B 如果某一特定元素大于或者小 ...

  8. ST算法

    作用:ST算法是用来求解给定区间RMQ的最值,本文以最小值为例 举例: 给出一数组A[0~5] = {5,4,6,10,1,12},则区间[2,5]之间的最值为1. 方法:ST算法分成两部分:离线预处 ...

  9. 求解区间最值 - RMQ - ST 算法介绍

    解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...

随机推荐

  1. Firefox渗透测试黑客插件集

    前天看S哥用Firefox的hackbar进行手动注入进行渗透,觉得直接运用浏览器的插件进行渗透测试有很多优点,既可以直接在前端进行注入等操作,也可以省却了寻找各种工具的麻烦.前端还是最直接的!于是这 ...

  2. Coursera台大机器学习课程笔记13 -- Regularization

    这一节讲的是正则化,在优化中一直会用到正则化项,上课的时候老师一句话代过,没有作过多的解释.听完这节课后, 才明白好大学和野鸡大学的区别有多大.总之,这是很有收获的一节课. 首先介绍了为什么要正则化, ...

  3. css form 表单组对齐

    2014年7月1日 15:31:17 第一次写css,见谅 css: .form-box .form-group .form-label {text-align: right; width: 200p ...

  4. MySQL入门书籍和方法分享

    本文罗列了一些适用于MySQL及运维入门和进阶使用的书籍. 背景:各大论坛上总是有很多同学咨询想学习数据库,或者是为入行DBA做些准备.几年来作为一个MySQL DBA的成长过程有一些积累和感悟,特此 ...

  5. Java for LeetCode 151 Reverse Words in a String

    Given an input string, reverse the string word by word. For example, Given s = "the sky is blue ...

  6. Extjs读取更改或者发送ajax返回请求的结果简单封装

    Extjs的submit()方法提交的数据:如下: this.formPanel.getForm().submit({                url:this.saveUrl,         ...

  7. Lubuntu下配置Python开发环境

    安装完系统必须要做的几件事: 一.更新软件    (如果是通过最新版镜像安装,可无视此步骤)    1.选择速度比较快的源,默认的源速度不一定快.二.配置终端    1.设置终端背景,前景色,透明度  ...

  8. 数列(codevs 1141)

    题目描述 Description 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列,例如,当k=3时,这个序列是: 1,3,4,9,10,12,13 ...

  9. 制做RPM包

    http://nmshuishui.blog.51cto.com/1850554/1583117 [root@NGM ~]# yum install pcre-devel zlib-devel ope ...

  10. Linux内核NAPI机制分析

    转自:http://blog.chinaunix.net/uid-17150-id-2824051.html 简介:NAPI 是 Linux 上采用的一种提高网络处理效率的技术,它的核心概念就是不采用 ...