CF359D-Pair of Numbers

CF359D-Pair of Numbers

题目大意

你有一个数组 \(a\) ,包含 \(n\) 个数字。你要找到一对整数对,使得

· 存在整数 \(j\) ,\((l \le j \le r),\) \(a_l,…,a_r\)

· 值 \(r-l\) 取到最大值

找出所有对应 \(r-l\) 最大值的 \(l\) 位置。

\(Hint\)

考虑怎样的区间 \([l,r]\) 能满足上述条件。不难发现是 区间 \(gcd\) 等于 区间 \(min\)

题解

对于 \(r-l\) 的值,考虑二分答案。

接下来对于每一个 \(i\) ,判断其 \([i,i+r-l]\) 区间 \(gcd\) 等于 区间 \(min\) 。用 \(st\) 表维护静态区间 \(gcd\)\(min\)。记录满足条件的位置。

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define umap unordered_map
#define endl '\n'
using namespace std;
using i128 = __int128;
const int mod =1e9+7;
template <typename T>void read(T&x){
    x=0;int f = 1;
    char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    for(;isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c^48);
    x*=f;
}
template <typename T>void print(T x) {
     if (x < 0) { putchar('-'); x = -x; }
     if (x > 9) print(x / 10);
     putchar(x % 10 + '0');
}
#define int long long
const int maxn=3e5+10;
int a[maxn],dp[maxn][22],dpgcd[maxn][22];
void stmin(int n)
{
    for (int i=1;i<=n;i++)
        dp[i][0]=a[i];
    for (int j=1;j<=21;j++)
        for (int i=1;i+(1<<j)-1<=n;i++)
            dp[i][j]=min(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);	
}
int querymin(int l,int r)
{
    int k=log2(r-l+1);
    return min(dp[l][k],dp[r-(1<<k)+1][k]);
}

void stgcd(int n)
{
    for (int i=1;i<=n;i++)
        dpgcd[i][0]=a[i];
    for (int j=1;j<=21;j++)
        for (int i=1;i+(1<<j)-1<=n;i++)
            dpgcd[i][j]=gcd(dpgcd[i][j-1],dpgcd[i+(1<<(j-1))][j-1]);	
}
int querygcd(int l,int r)
{
    int k=log2(r-l+1);
    return gcd(dpgcd[l][k],dpgcd[r-(1<<k)+1][k]);
}
const int N=500005;
const int M=2000005;
inline void solve()
{
	vector<int> ans;
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	stmin(n);stgcd(n);
	int l=0,r=n;
	while(l<r)
	{
		vector<int> temp;
		int mid=l+r+1>>1;
		for(int i=1;i+mid<=n;i++)
		{
			if(querymin(i,i+mid)==querygcd(i,i+mid))
			{
				temp.push_back(i);
			}
		}
		if(temp.size()==0)
		{
			r=mid-1;
		}
		else
		{
			l=mid;
			ans=temp;
		}
	}
	if(l==0)
	{
		cout<<n<<" "<<0<<endl;
		for(int i=1;i<=n;i++) cout<<i<<" ";
		return;
	}
	cout<<ans.size()<<" "<<l<<endl;
	for(int i=0;i<ans.size();i++)
	{
		cout<<ans[i]<<" ";
	}
	cout<<endl;
}

signed main()
{
//	ios;
	int T=1;
//	cin>>T;
	for(;T--;) solve();
	return 0;
}

posted @ 2025-11-22 14:55  NDAKJin  阅读(3)  评论(0)    收藏  举报