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


    原题链接: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];//gcd
    int dq[MAXN][20];//min
    int 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;
    		else
    			r = mid-1;
    	}
    		
    
    	out(l);
    	return 0;
    }


  • 相关阅读:
    初始化操作由“case”标签跳过
    NI采集卡DO例程2 WriteDigChanExtClk
    QT中QString 类的使用获取指定字符位置、截取子字符串等
    NI采集卡DO例程1 WriteDigChan
    springboot链路追踪ID
    Java读取pem文件使用RSA加密解密
    docker安装logstash并读取syslog数据
    MySQL事务隔离级别
    Golang的RSA加密
    springboot整合log4j
  • 原文地址:https://www.cnblogs.com/riskyer/p/3424141.html
Copyright © 2020-2023  润新知