codeforce 359D 二分+ 动态规划(sparse table)

来源:互联网 发布:python 获取微秒 编辑:程序博客网 时间:2024/06/05 02:55

原题链接:http://codeforces.com/problemset/problem/359/D

思路:首先对符合题目的长度(r-l)从0到n-1进行二分查找,对每一个长度进行check,看是否满足条件。

满足条件的话需要区间【l,r】内的最小值和最大公约数相等,如果暴力搜索,会超时,故采用st(sparse table)算法,建立table只需要O(nlgn)时间,查询是O(1),远远小于暴力搜索

st算法具体可参考http://baike.baidu.com/view/1536346.htm#2,只要适用于一段区间内的最大最小等值的计算。


AC代码如下:

#include <iostream>#include <cstdio>#include <iomanip>#include <algorithm>#include <map>#include <set>#include <string>#include <vector>#include <string.h>#include <math.h>using namespace std;typedef  long long ll;const int MAXN = 300050;int arr[MAXN];int dp[MAXN][20];//gcdint dq[MAXN][20];//minint n;int gcd(int a,int b){return b?gcd(b,a%b):a;}bool ok(int x){int k = (int)(log((double)(x+1)) / log(2.0));for(int i=0;i<n-x;i++){int j = i+x;int Min = min(dq[i][k],dq[j - (1<<k) + 1][k]);int g = gcd(dp[i][k],dp[j - (1<<k) + 1][k]);if(g==Min)return true;}return false;}void out(int x){vector<int> v;int k = (int)(log((double)(x+1)) / log(2.0));if(x>0){for(int i=0;i<n-x;i++){int j = i+x;int Min = min(dq[i][k],dq[j - (1<<k) + 1][k]);int g = gcd(dp[i][k],dp[j - (1<<k) + 1][k]);if(g==Min){v.push_back(i);}}}else{for(int i=0;i<n;i++)v.push_back(i);}cout<<v.size()<<" "<<( x>0?x:0)<<endl;for(int i=0;i<v.size();i++)cout<<v[i]+1<<" ";cout<<endl;}int main(){cin>>n;for(int i=0;i<n;i++)cin>>arr[i];for(int i=0;i<n;i++){dp[i][0] = arr[i];dq[i][0] = arr[i];}for(int i=1;i<20;i++)for(int j = 0;j<n;j++){dp[j][i]=dp[j-1][i];dq[j][i] = dq[j-1][i];if(j+(1<<(i-1))<n){dq[j][i] = min(dq[j][i-1],dq[j+(1<<(i-1))][i-1]); dp[j][i] = gcd(dp[j][i-1],dp[j+(1<<(i-1))][i-1]);}}int l = 0;int r = n-1;while(l<r){int mid = (l+r+1)/2;if(ok(mid))l = mid;elser = mid-1;}out(l);return 0;}