CodeForces 359D (数论+二分+ST算法)
题目链接: 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算法)的更多相关文章
- codeforces 359D 二分答案+RMQ
上学期刷过裸的RMQ模板题,不过那时候一直不理解>_< 其实RMQ很简单: 设f[i][j]表示从i开始的,长度为2^j的一段元素中的最小值or最大值 那么f[i][j]=min/max{ ...
- HDU 5289 Assignment (ST算法区间最值+二分)
题目链接:pid=5289">http://acm.hdu.edu.cn/showproblem.php?pid=5289 题面: Assignment Time Limit: 400 ...
- 【原创】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算法作 ...
- hdu5289 Assignment (区间查询最大值最小值,st算法...)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5289 题意:给定长度为n的序列a和一个整数K,找出最大值和最小值的差值小于K的区间.输出满足条件的区间的个 ...
- AcWing ST算法(区间求最值)打卡
一,介绍 ST算法是一个用倍增来求区间最值的算法,倍增是一个与二分类似的思想的一个东西,倍增简而言之也就是区间长度按1,2,4,8..... 我们先用nlog(n)的复杂度打出一个最大值表,后面我们可 ...
- Java实现的二分查找算法
二分查找又称折半查找,它是一种效率较高的查找方法. 折半查找的算法思想是将数列按有序化(递增或递减)排列,查找过程中采用跳跃式方式查找,即先以有序数列的中点位置为比较对象,如果要找的元素值小 于该中点 ...
- c#-二分查找-算法
折半搜索,也称二分查找算法.二分搜索,是一种在有序数组中查找某一特定元素的搜索算法. A 搜素过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则搜素过程结束: B 如果某一特定元素大于或者小 ...
- ST算法
作用:ST算法是用来求解给定区间RMQ的最值,本文以最小值为例 举例: 给出一数组A[0~5] = {5,4,6,10,1,12},则区间[2,5]之间的最值为1. 方法:ST算法分成两部分:离线预处 ...
- 求解区间最值 - RMQ - ST 算法介绍
解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...
随机推荐
- C#父类子类对象关系
案例: 主要有Vehicle.cs Airplane.cs Car.cs 3个类. Car和Airplane都继承与Vehicle类.Vehicle中Drive为虚方法,可在子类中重写,父类引 ...
- RouterOS DNS劫持 -- A记录
通常我们使用RouterOS的DNS主要是用于实现DNS缓存功能,即由RouterOS实现DNS服务器解析功能,除了这个功能,RouterOS可以实现对内网域名解析劫持,即实现路由网关的A记录查询. ...
- django-cms 代码研究(四)CMS_TEMPLATE标签
CMS_TEMPLATE 继承这个东东可以在实现很灵活的布局,如下:
- 【云计算】mesos生态系统
以 Apache Mesos 计算的开源数据中心 数据中心 易云 · 2015-09-15 16:53 Apache Mesos 是一个管理器,它通过分布式的应用或框架提供了一种高效的资源隔离和共享. ...
- css+div绝对定位
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" ...
- iOS7 中的JavaScriptCore简单介绍
以前写过一篇介绍如何使用第三方库在ios上进行js和oc交互调用的文章,链接如下 iOS 使用UIWebView把oc代码和javascript相关联.当时建立项目时,仍然是ios6时代,所以没有原生 ...
- MFC dfs遍历文件
//如果涉及到大文件的遍历(大于4GB),可以将以下代码_finddata_t换成__finddata64_t,_findfirst换成_findfirst64,_findnext换成_findnex ...
- [SVN(ubuntu)] svn 文件状态标记含义
A item 文件.目录或是符号链item预定加入到版本库. C item 文件item发生冲突,在从服务器更新时与本地版本发生交迭,在你提交到版本库前,必须手工的解决冲突. D item 文件.目录 ...
- MapReduce:详解Shuffle过程(转)
/** * author : 冶秀刚 * mail : dennyy99@gmail.com */ Shuffle过程是MapReduce的核心,也被称为奇迹发生的地方.要想理解MapRedu ...
- Web服务器原理及简单实现
Web系统由客户端(浏览器)和服务器端两部分组成.Web系统架构也被称为B/S架构.最常见的Web服务器有Apache.IIS等,常用的浏览器有IE.Firefox.chrome等.当你想访问一个网页 ...