码迷,mamicode.com
首页 > 其他好文 > 详细

CF359D Pair of Numbers [RMQ+ST算法]

时间:2014-09-01 14:05:53      阅读:248      评论:0      收藏:0      [点我收藏+]

标签:style   color   os   io   for   log   sp   amp   on   

题意:

给一串数,找出最长的区间使得这个区间里面有个数能被其他所有数整除(包括它自己),求满足这个条件的最长区间的个数及长度,以及这些区间的左端的位置

分析:

这个区间的要求其实就是GCD(ALL)=MIN(ALL),能被其他数整除,这个数肯定是最小的,然后又能被其他数整除(包括自己)这个数就是GCD了


可以二分枚举区间长度,然后验证答案的可靠性

对当前长度的所有区间,套用RMQ,验证是否存在一个区间的GCD=MIN

如果有这样的一个区间,那么说明当前长度可以,加大枚举的区间长度,否则减小

#include<iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
#include<cmath>
using namespace std;
#define MAXN 333333
int N;
int gcd(int a,int b){return b==0?a:gcd(b,a%b);}
int num[MAXN];
int f1[MAXN][30];
int f2[MAXN][30];
void st(int n) {
	int i, j, k, m;
	k = (int) (log((double)n) / log(2.0));
	for(i = 0; i < n; i++) {
		f1[i][0] = num[i];
		f2[i][0] = num[i];
	}
	for(j = 1; j <= k; j++) {
		for(i = 0; i + (1 << j) - 1 < n; i++) {
			m = i + (1 << (j - 1));
			f1[i][j] = min(f1[i][j-1], f1[m][j-1]);
			f2[i][j] = gcd(f2[i][j-1], f2[m][j-1]);
		}
	}
}

//查询i和j之间的最值,注意i是从0开始的
int rmq_gcd(int i, int j) {
	int k = (int)(log(double(j-i+1)) / log(2.0)), t2;
	t2 = gcd(f2[i][k], f2[j - (1<<k) + 1][k]);
	return t2;
}
int rmq_min(int i, int j) {
	int k = (int)(log(double(j-i+1)) / log(2.0)), t1;
	t1 = min(f1[i][k], f1[j - (1<<k) + 1][k]);
	return t1;
}
bool check(int l){
        for(int i=0;i<N && i<=N-l;i++){
                if(rmq_gcd(i,i+l-1)==rmq_min(i,i+l-1))
                        return true;
        }
        return false;
}
vector<int>ans;
void get(int l){
        for(int i=0;i<N && i<=N-l;i++){
                if(rmq_gcd(i,i+l-1)==rmq_min(i,i+l-1))
                        ans.push_back(i+1);
        }
}
int main() {
#ifndef ONLINE_JUDGE
	freopen("/home/rainto96/in.txt","r",stdin);
#endif

	int i;
	scanf("%d", &N);
	for (i = 0; i < N; i++) {
		scanf("%d", num+i);
	}
	st(N);
	int l=1,r=N,mid=(l+r)/2+1;
	while(l<r){
                if(check(mid))l=mid;
                else          r=mid-1;
                mid=(l+r)/2+1;
	}
	get(l);
	cout<<ans.size()<<' '<<l-1<<endl;
	for(int i=0;i<ans.size();i++){
                cout<<ans[i]<<' ';
	}
	cout<<endl;
	return 0;
}


CF359D Pair of Numbers [RMQ+ST算法]

标签:style   color   os   io   for   log   sp   amp   on   

原文地址:http://blog.csdn.net/u011775691/article/details/38978855

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!